目录
一、效果图
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了。
还是那句话,获取源码或如需帮助,通过博客后面名片+作者即可!