您现在的位置是:首页 >技术教程 >vue实现好看的相册、图片网站网站首页技术教程

vue实现好看的相册、图片网站

愛芳芳 2023-05-15 12:00:03
简介vue实现好看的相册、图片网站

目录

一、效果图

1.项目访问地址

2.画虫官方效果图:

3.作者实现的效果图:

二、代码实现

1.项目结构截图

2.路由配置代码:

3. 头部+底部+主页面内容显示容器的代码

4.首页,即标签页的代码

三、项目启动说明

四、总结

 


一、效果图

仿照画虫的标签、摄影师和标签详情图片列表分别写了几个完整的页面,同时搭了整个网站的基础布局框架,仿照还原度1比1来实现,以下分别是画虫官方效果图和作者demo效果图。

1.项目访问地址

作者demo预览:点击访问

官方画虫:点击访问 

 

2.画虫官方效果图:

标签: 

标签图片列表:

 

 摄影师列表:

 

 3.作者实现的效果图:

 

 

二、代码实现

1.项目结构截图

components为登录注册组件窗口,page为网站布局实现,头部+底部+主页面内容显示容器,views存放具体功能页面,router为路由配置。

2.路由配置代码:

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/page/index/index';
Vue.use(Router);


export const constantRoutes = [
    {
      path: '/index',
      component: Layout,
      redirect: '/explore',
      children: [{
        path: 'explore',
        name: '主页',
        component: () =>
          import( /* webpackChunkName: "views" */ '@/views/home/index'),
        children:[
          {
            path: '/explore',
            name: '首页-标签列表',
            component: () => import( '@/views/home/explore/index')
          },
          {
            path: '/photographer',
            name: '首页-摄影师列表',
            component: () => import( '@/views/home/photographer/index')
          }
        ]
      }]
    },
    {
      path: '/',
      name: '主页',
      redirect: '/index'
    },
    {
      path: '/tags',
      component: Layout,
      children: [{
        path: '',
        name: '标签',
        component: () =>
          import( /* webpackChunkName: "views" */ '@/views/tags/index'),
      }]
    },
  ];

const createRouter = () => new Router({
  // mode: 'history', // require service support
  scrollBehavior: () => ({
    y: 0
  }),
  routes: constantRoutes
})

const router = createRouter()

// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

3. 头部+底部+主页面内容显示容器的代码

头部代码:

<template>
  <header class=" ">
    <nav class="nav-wide">
      <div class="nav-left">
        <a @click="homePage">
          <i class="nav-logo"></i>
        </a>
        <ul class="supnav-list">
          <li class="supnav-item"><a target="_blank" rel="noopener" class="">视频素材</a></li>
          <li class="supnav-item"><a class="" @click="homePage">首页</a></li>
          <li class="supnav-item"><a class="">社区</a></li>
          <li class="supnav-item"><a class="">活动</a></li>
          <li class="supnav-item"><a class="video_enter ">短视频</a><i class="subnav-red-tip-video" style="display: inline;"></i></li>
          <li class="supnav-item subnav-trigger tuchong_stock_enter_list">
            <a class="">发现<i class="supnav-red-tip"></i></a>
            <ul class="subnav-list">
              <li @click="homePage"><a>标签</a></li>
              <li><a>摄影师</a></li>
              <li><a>影像频道</a></li>
              <li><a>教程</a></li>
              <li><a>器材</a></li>
              <li class="tuchong_stock_enter"><a>正版图片下载</a><i class="subnav-red-tip" style="display: inline;"></i></li>
            </ul>
          </li>
          <li class="supnav-item subnav-trigger">
            <a class="">更多</a>
            <ul class="subnav-list">
              <li><a>创意图库</a></li>
              <li><a>下载APP</a></li>
              <li><a>商务合作</a></li>
            </ul>
          </li>
        </ul>
      </div>
      <div class="nav-right">
        <!-- <div class="nav-search">
            <i class="icon-search J-search-btn"></i>
            <form action="https://tuchong.com/search/all/" method="get">
                <input required class="search-input" type="text" name="query" placeholder="搜索" autocomplete="off">
            </form>
        </div> -->
        <!-- 非登录状态 -->
        <a class="nav-login login-trigger" @click="openLoginModal">登录</a>
        <a class="nav-register register-trigger" @click="openRegisterModal">注册</a>
      </div>
    </nav>

    <login-modal ref="loginModal"></login-modal>
    <register-modal ref="registerModal"></register-modal>
  </header>
</template>

<script>
  import { mapGetters } from 'vuex';
  import loginModal from "../../components/login_modal.vue";
  import registerModal from "../../components/register_modal.vue";

  export default {
    components: {
      loginModal,
      registerModal
    },
    data() {
      return {
        input: ''
      };
    },
    mounted() {
    },
    methods: {
      homePage(){
        this.$router.push({path: '/index'});
      },
      openLoginModal(){
        this.$refs.loginModal.openModal();
      },
      openRegisterModal(){
        this.$refs.registerModal.openModal();
      }
    }
  };
</script>

<style scoped>
  header {
    position: relative;
    min-width: 100%;
    height: 60px;
    margin: 0 auto;
    background-color: #000;
    font-weight: 500;
    z-index: 4;
  }
  header .nav-wide {
    min-width: 800px;
    /*max-width: 1880px;*/
    padding: 0 40px;
    margin: 0 auto;
  }
  header .nav-wide:after {
    display: block;
    clear: both;
    content: "";
    visibility: hidden;
    height: 0;
  }
  header .nav-wide .nav-left {
    float: left;
    height: 60px;
    font-size: 0;
  }
  .supnav-list .supnav-item>a:hover {
    color: #c99a05;
  }
  a {
    text-decoration: none;
    cursor: pointer;
    color: inherit;
  }
  header .nav-logo {
    display: inline-block;
    height: 22px;
    width: 80px;
    margin: 19px 0;
    background-image: url("../../../public/img/logo.png");
    -moz-background-size: 100% 100%;
    background-size: 100% 100%;
  }
  .nav-left .supnav-list {
    margin-left: 24px;
  }
  .supnav-list {
    display: inline-block;
    vertical-align: top;
    line-height: 1;
    font-size: 0;
  }
  ul, li, p {
    padding: 0;
    margin: 0;
    list-style: none;
  }
  .supnav-list .supnav-item {
    position: relative;
    display: inline-block;
    vertical-align: top;
    font-size: 14px;
  }
  ul, li, p {
    padding: 0;
    margin: 0;
    list-style: none;
  }
  .supnav-list .supnav-item a {
    display: block;
    line-height: 60px;
    color: #fff;
    font-weight: 500;
  }
  .nav-left .supnav-item>a {
    position: relative;
    padding: 0 12px;
    letter-spacing: 2px;
  }

  a {
    text-decoration: none;
    cursor: pointer;
    color: inherit;
  }
  .supnav-list .subnav-list {
    position: absolute;
    top: 59px;
    z-index: 1;
    left: 50%;
    display: none;
    width: 130px;
    margin-top: 1px;
    margin-left: -65px;
    line-height: 1;
    opacity: 0;
    -webkit-transition: opacity .5s ease;
    -moz-transition: opacity .5s ease;
    transition: opacity .5s ease;
    border-top: 10px solid rgba(0,0,0,0);
  }
  .supnav-list .subnav-list li:first-child {
    padding-top: 10px;
  }
  .supnav-list .subnav-list li {
    position: relative;
    background-color: #222;
  }
  .supnav-list .subnav-list li a {
    display: block;
    height: 40px;
    line-height: 40px;
    color: #fff;
    text-align: center;
  }
  .supnav-list .subnav-list li:last-child {
    padding-bottom: 10px;
  }
  header .nav-wide .nav-right {
    float: right;
    height: 60px;
    font-size: 0;
  }
  .nav-register, .nav-login {
    display: inline-block;
    margin-top: 12px;
    margin-left: 30px;
    height: 36px;
    line-height: 36px;
    color: #fff;
    font-size: 14px;
  }
  .nav-register {
    width: 100px;
    text-align: center;
    background-color: #c99a05;
  }
  .nav-register, .nav-login {
    display: inline-block;
    margin-top: 12px;
    margin-left: 30px;
    height: 36px;
    line-height: 36px;
    color: #fff;
    font-size: 14px;
  }
  header .nav-wide:after {
    display: block;
    clear: both;
    content: "";
    visibility: hidden;
    height: 0;
  }
  .supnav-list .subnav-list li::after {
    content: attr(data-count);
    position: absolute;
    left: 69px;
    top: 7px;
    padding: 0 4px;
    -webkit-border-radius: 7px;
    -moz-border-radius: 7px;
    border-radius: 7px;
    font-size: 12px;
    color: #fff;
    background-color: #e60905;
    line-height: 14px;
  }
  .supnav-list .subnav-list:after {
    content: "";
    position: absolute;
    top: -1px;
    left: 0;
    width: 100%;
    height: 1px;
  }
  .nav-left .supnav-item i {
    display: none;
    position: absolute;
    top: 18px;
    right: 8px;
    width: 6px;
    height: 6px;
    -webkit-border-radius: 100%;
    -moz-border-radius: 100%;
    border-radius: 100%;
    background: red;
  }
  .supnav-list .subnav-trigger:hover .subnav-list {
    display: block;
    opacity: 1;
  }
  .supnav-list .subnav-list li a:hover {
    color: #c99a05;
  }
</style>

布局整合代码:

<template>
  <div class="page-scroll" style="width: 100%;height: 100%;overflow: auto;background: #f5f7f9;">
    <top></top>
    <router-view></router-view>
    <foot></foot>
    <el-backtop target=".page-scroll" :bottom="100">
      <div
        style="{
        height: 100%;
        width: 100%;
        background-color: gray;
        box-shadow: 0 0 6px rgba(0,0,0, .12);
        text-align: center;
        line-height: 40px;
        color: #FFFFFF;
      }"
      >
        UP
      </div>
    </el-backtop>
  </div>
</template>

<script>
  import top from "../top/index.vue";
  import foot from "../foot/index.vue";

  export default {
      components: {
        top,
        foot
      },
      name: "index",
      data() {
        return {
        };
      },
      mounted() {
      },
      methods: {
      }
    };
</script>

<style>
</style>

4.首页,即标签页的代码

<template>
  <main>
    <div class="container">
      <nav class="secondary-nav">
        <ul class="nav-list">
          <li v-for="(item,index) in menus" :key="index" :class="item.path===path?'active':''" @click="selTab(item)">
            <a target="_self" class="subnav-text">
              {{item.name}}
            </a>
          </li>
        </ul>
      </nav>
      <router-view></router-view>
    </div>
  </main>
</template>

<script>
  export default {
    data() {
      return {
        path:'/explore',
        menus: [
          {name:'标签',path:'/explore'},
          {name:'摄影师',path:'/photographer'},
          {name:'影像频道',path:'/videoChannel'},
          {name:'教程',path:'/course'},
          {name:'器材',path:'/equipment'}
        ]
      };
    },
    mounted() {
      let that = this;
      setInterval(function(){
        that.path = that.$router.currentRoute.path;
      },1000)
    },
    methods: {
      selTab(item){//标签切换
        this.path = item.path;
        this.$router.push({path: item.path});
      },
    }
  };
</script>

三、项目启动说明

项目是传统vue项目,实现需要安装node js,然后依次成功执行

npm install

npm run dev

顺利的话就这么简单,当然,遇到问题,直接call me(私聊作者获取帮助,作者一直在帮助了很多的小伙伴)

四、总结

第一步暂时到这里,关注作者,及时了解更多好项目!如果你也有好的案例,欢迎分享出来,说不定下一个demo就ta了。

还是那句话,获取源码或如需帮助,通过博客后面名片+作者即可!

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。