我从未见过这么美妙的项目,当然与我接触的项目少有关,但是这个项目满满的艺术气息,让人沉醉,让人忍不住的去研究代码。
先放项目地址:https://github.com/eidonlon/imitate-beautiful-thing
再来看一下项目的效果
接下来我们来研究代码吧~
我们先来看项目的入口文件main.js
main.js作为入口引入App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
};
</script>
我们来分析main.js里面的内容,逐条分析
关于引入的路由
import Vue from 'vue'
import Router from 'vue-router'
// 这种也好玩,引入组件,再在router中注册
import pageView from '@/pages/pageView'
import Home from '@/pages/home'
import Things from '@/pages/things'
import Designer from '@/pages/designer'
import Personal from '@/pages/personal'
import Pictoral from '@/pages/pictoral'
import Details from '@/pages/details'
import Comment from '@/pages/comment'
import About from '@/pages/about'
Router.prototype.goBack = function(){
this.isBack = true;
window.history.go(-1);
};
Vue.use(Router);
const routers = new Router({
routes: [
{
path:'',
name:'',
component:pageView,
children:[
{
path:'/',
name:'',
component:Home,
children:[
{
path:'',
name:'pictoral',
meta:{index:1},
component:Pictoral
},
{
path:'/things',
name:'things',
meta:{index:1},
component:Things
},
{
path:'/designer',
name:'designer',
meta:{index:1},
component:Designer
},
{
path:'/personal',
name:'personal',
meta:{index:1},
component:Personal
},
]
},
{
path:'/details/:id',
name:'details',
meta:{index:2},
component:Details
},
{
path:'/comment/:id',
name:'comment',
meta:{index:2},
component:Comment
},
{
path:'/about',
name:'about',
meta:{index:2},
component:About
}
]
}
]
})
routers.beforeEach(function (to, from, next) {
document.body.scrollTop = document.documentElement.scrollTop = 0
// 进入下一个页面的时候,都是页面的top为0那种
next()
});
export default routers;
我们会发现引入了vue-scroller,这个其实是实现下拉刷新,上拉获取数据的功能的。
store中的内容不多,只是对tabIndex做了一个简单的下标赋值
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state:{
tabIndex:0
},
mutations:{
changeTab: function(state,index){
state.tabIndex = index;
}
}
});
export default store
在mian.js页面还引入了tabBar,swiper,toast组件
先看tabBar组件
<template>
<div class="tab-bar">
<ul>
<li v-for="(item,index) in itemList"
:key="index" class="tab-bar-item"
:class="{active: index == isActive}"
@click="addActive(index,item)">
<span class="tab-bar-item_icon" :class="item.icon"></span>
<span class="tab-bar-item_Text">{{item.text}}</span>
</li>
</ul>
</div>
</template>
<script>
export default{
name:'tabbar',
data (){
return {
isActive:this.$store.state.tabIndex,
itemList:[
{text:"推荐",icon:"fa fa-clipboard",link:'/'},
{text:"作品",icon:"fa fa-smile-o",link:'/things'},
{text:"设计师",icon:"fa fa-pencil",link:'/designer'},
{text:"我",icon:"fa fa-user-o",link:'/personal'}
]
}
},
mounted(){
if(this.isActive != 0){
this.$router.push(this.itemList[this.isActive].link);
}
},
methods:{
addActive: function(index,item){
console.log('.....index',index)
console.log('...item',item.link)
this.isActive = index;
this.$router.push(item.link);
this.$store.commit("changeTab",index);
}
}
};
</script>
//swiper.vue
<template>
<div class="swiper-box">
<swiper :options="swiperOption" ref="swiper" >
<swiper-slide v-for="(data, index) in dataList"
:key="index"
:class="{active: activeIndex == index}">
<slot name="swiperMain" :data="data">{{data.text}}</slot>
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</template>
<script>
import 'swiper/dist/css/swiper.css'
import { swiper, swiperSlide} from 'vue-awesome-swiper'
export default{
name: 'appnav',
props:{
activeIndex:{},
swiperOption:{
type:Object
},
dataList:{}
},
components:{
swiper,
swiperSlide
}
};
</script>
//toast.vue
<template>
<transition name="toast-fade">
<div class="toast" v-show="visible" >
<div class="toast-content">{{message}}</div>
</div>
</transition>
</template>
<script>
export default {
name:'toast',
data(){
return {
visible:false,
message:''
}
}
}
</script>
//main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store'
import scroller from 'vue-scroller'
import 'font-awesome/scss/font-awesome.scss'
import './assets/style/reset.css'
import './assets/style/style.scss'
import tabbar from './components/tabBar'
import swiper from './components/swiper'
import toast from './components/toast'
Vue.config.productionTip = false
Vue.config.devtools = true
Vue.prototype.$axios = axios;
Vue.use(scroller)
Vue.use(tabbar)
Vue.use(swiper)
Vue.use(toast)
new Vue({
router,
store,
components: { App },
render: h => h(App),
}).$mount("#app");
接下来我们结合router来看页面
//src\pages\pageView.vue
<template>
<div class="page-view">
<transition :name="transitionName">
<router-view class="child-view"></router-view>
</transition>
</div>
</template>
<script>
export default {
name:"pageView",
data() {
return {
transitionName:'slide-left'
}
},
watch:{
$route: function(to,from){
console.log('what is to',to)
console.log('what is from',from)
let isBack = this.$router.isBack;
if(isBack){
this.transitionName = 'slide-right';
}else{
this.transitionName = 'slide-left';
}
this.$router.isBack = false;
},
}
}/* */
</script>
//src\pages\pageView.vue
<template>
<div class="tab-bar">
<ul>
<li v-for="(item,index) in itemList"
:key="index" class="tab-bar-item"
:class="{active: index == isActive}"
@click="addActive(index,item)">
<span class="tab-bar-item_icon" :class="item.icon"></span>
<span class="tab-bar-item_Text">{{item.text}}</span>
</li>
</ul>
</div>
</template>
<script>
export default{
name:'tabbar',
data (){
return {
isActive:this.$store.state.tabIndex,
itemList:[
{text:"推荐",icon:"fa fa-clipboard",link:'/'},
{text:"作品",icon:"fa fa-smile-o",link:'/things'},
{text:"设计师",icon:"fa fa-pencil",link:'/designer'},
{text:"我",icon:"fa fa-user-o",link:'/personal'}
]
}
},
mounted(){
if(this.isActive != 0){
this.$router.push(this.itemList[this.isActive].link);
}
},
methods:{
addActive: function(index,item){
console.log('.....index',index)
console.log('...item',item.link)
this.isActive = index;
this.$router.push(item.link);
this.$store.commit("changeTab",index);
}
}
};
</script>
效果为
代码为:
<template>
<div class="personal">
<div class="personal-logo">
<div class="logo">
<span class="logo_img"><img src="/static/images/logo.jpg" alt=""></span>
<span>登录</span>
</div>
</div>
<div class="personal-main">
<div class="personal-main_menu">
<ul>
<li><i class="fa fa-thumbs-o-up"></i><span>我推荐的</span></li>
<li><i class="fa fa-heart-o"></i><span>我关注的</span></li>
<li><i class="fa fa-folder-open-o"></i><span>我的作品</span></li>
</ul>
</div>
<div class="personal-main_list">
<ul>
<li><i class="fa fa-bell-o"></i><span>消息中心</span><i class="fa fa-angle-right"></i></li>
<li><i class="fa fa-bullhorn"></i><span>联系我</span><i class="fa fa-angle-right"></i></li>
<li @click="toAbout"><i class="fa fa-meh-o"></i><span>关于</span><i class="fa fa-angle-right"></i></li>
</ul>
</div>
</div>
</div>
</template>
<script>
import {prevent} from '../utils'
export default{
name: 'personal',
mounted(){
document.body.removeEventListener("touchmove",prevent);
},
methods: {
toAbout:function(){
this.$router.push("/about");
}
}
};
</script>
//src\pages\about.vue
<template>
<div class="about">
<div class="page-title">
<span @click="goBack" class="goBack"><i class="fa fa-2x fa-angle-left"></i></span>
<h3>关于</h3>
</div>
<div class="main">
<p>声明:这只是一个练习的demo :( </p>
</div>
</div>
</template>
<script>
export default{
name: '',
data (){
return{
desc:''
}
},
methods: {
goBack: function(){
this.$router.goBack();
}
}
};
</script>
//src\pages\things.vue
<template>
<div class="things">
<div class="things-nav">
<swiper :dataList="navList" :activeIndex="activeIndex" ref="navSwiper" :swiperOption="swiperOptionNav" ></swiper>
</div>
<div class="things-main">
<scroller
:on-refresh="refresh"
:refreshText="refreshText" ref="scroller">
<span style="width:20px;height:20px;" class="spinner" slot="refresh-spinner"></span>
<div class="things-time">TODAY</div>
<swiper
:dataList="navList"
:swiperOption="swiperOptionMain" ref="mainSwiper">
<div slot="swiperMain" slot-scope="slotProps">
<div v-for="(item, index) in slotProps.data.dataList" :key="index" class="things-item" >
<div class="things-img-wrapper" @click="showDetails(item.id)">
<img class="things-item_img" :src="item.img" alt="">
<span class="things-item_tips">{{item.author}}</span>
</div>
<div class="things-item-foot">
<div class="foot-desc">
<span class="foot-desc_logo"><img :src="item.icon" alt=""></span>
<div class="foot-desc_text">
<p>{{item.author}}</p>
<p class="origin">{{item.origin}}</p>
</div>
</div>
<div class="foot-action">
<span @click="like(item)" class="fa fa-meh-o action-up"></span><span v-show="item.likeNum" class="like">+<i>{{item.likeNum}}</i></span> | <span @click="dislike(item)" class="fa fa-frown-o action-down"></span><span v-show="item.dislikeNum" class="dislike"><i>{{item.dislikeNum}}</i></span>
</div>
</div>
</div>
</div>
</swiper>
</scroller>
<div class="to-top" @click="toTop"><i class="fa fa-arrow-up"></i></div>
</div>
</div>
</template>
<script>
import { mixin,pageAct } from '../utils'
export default{
name: 'things',
data (){
return{
likeNum:0,
dislikeNum:0,
}
},
mixins:[mixin,pageAct],
methods:{
showDetails: function(index){
this.$router.push("/comment/"+index);
},
getData: function(cb){
var self = this;
this.$axios.post("/things",{}).then(function(response){
console.log('aaaaa...',response)
var result = response.data;
if(result.code == 200){
self.navList = result.list;
}
}).catch(function(error){
console.log(error);
});
},
loadMore: function(cb){
var self = this;
this.$axios.post("/things",{author:self.activeIndex}).then(function(response){
var result = response.data;
cb && cb(result);
}).catch(function(error){
console.log(error);
});
}
}
};
</script>
//src\pages\designer.vue
<template>
<div class="designer">
<div class="designer-nav">
<swiper :dataList="navList" :activeIndex="activeIndex" ref="navSwiper" :swiperOption="swiperOptionNav" ></swiper>
</div>
<div class="designer-main">
<keep-alive>
<scroller :on-refresh="refresh" :refreshText="refreshText" ref="scroller">
<span style="width:20px;height:20px;" class="spinner" slot="refresh-spinner"></span>
<div class="designer-time">TODAY</div>
<swiper :dataList="navList" ref="mainSwiper" :swiperOption="swiperOptionMain">
<div slot="swiperMain" slot-scope="slotProps">
<div v-for="(item, index) in slotProps.data.dataList" :key="index" class="designer-item" >
<div class="designer-img-wrapper" @click="showDetails(item.id)">
<img class="designer-item_img" :src="item.img" alt="">
<span class="foot-desc_logo"><img :src="item.icon" alt=""></span>
</div>
<div class="designer-item-foot">
<div class="foot-desc">
<div class="foot-desc_text">
<p>{{item.author}} | <span class="origin">{{item.origin}}</span></p>
</div>
</div>
<div class="foot-action">
<span @click="showTotast" class="foot-actionr_follow">+ 关注</span>
</div>
</div>
</div>
</div>
</swiper>
</scroller>
</keep-alive>
<div class="to-top" @click="toTop">
<i class="fa fa-arrow-up"></i>
</div>
</div>
</div>
</template>
<script>
import {pageAct} from '../utils'
export default{
name: 'designer',
mixins:[pageAct],
methods:{
showDetails: function(index){
this.$router.push("/details/"+index);
},
getData: function(cb){
var self = this;
this.$axios.post("/designer",{}).then(function(response){
console.log('designer',response)
var result = response.data;
if(result.code == 200){
self.navList = result.list;
}
}).catch(function(error){
console.log(error);
});
},
loadMore: function(cb){
var self = this;
this.$axios.post("/designer",{author:self.activeIndex}).then(function(response){
var result = response.data;
cb && cb(result);
}).catch(function(error){
console.log(error);
});
},
showTotast: function(){
this.$toast({message:"敬请期待关注功能 :-)"});
}
}
};
</script>
```vue
//src\pages\details.vue
<span @click="goBack" class="goBack">
{{title}}
<img :src="img" alt="">
简介
<div class="desc-item" v-for="(item, index) in descList" :key="index">
<i class="fa" :class="item.icon">
{{item.tips}}:
{{item.text}}
其他作品
<div class="desc-img-item" v-for="(item, index) in imgList" :key="index">
—{{item.originate}}—
<img :src="item.img" alt="">