我从未见过这么美妙的项目,当然与我接触的项目少有关,但是这个项目满满的艺术气息,让人沉醉,让人忍不住的去研究代码。

先放项目地址:https://github.com/eidonlon/imitate-beautiful-thing

再来看一下项目的效果



接下来我们来研究代码吧~

我们先来看项目的入口文件main.js

main.js作为入口引入App.vue

  1. <template>
  2. <div id="app">
  3. <router-view></router-view>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'App'
  9. };
  10. </script>

我们来分析main.js里面的内容,逐条分析

关于引入的路由

  1. import Vue from 'vue'
  2. import Router from 'vue-router'
  3. // 这种也好玩,引入组件,再在router中注册
  4. import pageView from '@/pages/pageView'
  5. import Home from '@/pages/home'
  6. import Things from '@/pages/things'
  7. import Designer from '@/pages/designer'
  8. import Personal from '@/pages/personal'
  9. import Pictoral from '@/pages/pictoral'
  10. import Details from '@/pages/details'
  11. import Comment from '@/pages/comment'
  12. import About from '@/pages/about'
  13. Router.prototype.goBack = function(){
  14. this.isBack = true;
  15. window.history.go(-1);
  16. };
  17. Vue.use(Router);
  18. const routers = new Router({
  19. routes: [
  20. {
  21. path:'',
  22. name:'',
  23. component:pageView,
  24. children:[
  25. {
  26. path:'/',
  27. name:'',
  28. component:Home,
  29. children:[
  30. {
  31. path:'',
  32. name:'pictoral',
  33. meta:{index:1},
  34. component:Pictoral
  35. },
  36. {
  37. path:'/things',
  38. name:'things',
  39. meta:{index:1},
  40. component:Things
  41. },
  42. {
  43. path:'/designer',
  44. name:'designer',
  45. meta:{index:1},
  46. component:Designer
  47. },
  48. {
  49. path:'/personal',
  50. name:'personal',
  51. meta:{index:1},
  52. component:Personal
  53. },
  54. ]
  55. },
  56. {
  57. path:'/details/:id',
  58. name:'details',
  59. meta:{index:2},
  60. component:Details
  61. },
  62. {
  63. path:'/comment/:id',
  64. name:'comment',
  65. meta:{index:2},
  66. component:Comment
  67. },
  68. {
  69. path:'/about',
  70. name:'about',
  71. meta:{index:2},
  72. component:About
  73. }
  74. ]
  75. }
  76. ]
  77. })
  78. routers.beforeEach(function (to, from, next) {
  79. document.body.scrollTop = document.documentElement.scrollTop = 0
  80. // 进入下一个页面的时候,都是页面的top为0那种
  81. next()
  82. });
  83. export default routers;

我们会发现引入了vue-scroller,这个其实是实现下拉刷新,上拉获取数据的功能的。

store中的内容不多,只是对tabIndex做了一个简单的下标赋值

  1. //index.js
  2. import Vue from 'vue'
  3. import Vuex from 'vuex'
  4. Vue.use(Vuex)
  5. const store = new Vuex.Store({
  6. state:{
  7. tabIndex:0
  8. },
  9. mutations:{
  10. changeTab: function(state,index){
  11. state.tabIndex = index;
  12. }
  13. }
  14. });
  15. export default store

在mian.js页面还引入了tabBar,swiper,toast组件

先看tabBar组件

  1. <template>
  2. <div class="tab-bar">
  3. <ul>
  4. <li v-for="(item,index) in itemList"
  5. :key="index" class="tab-bar-item"
  6. :class="{active: index == isActive}"
  7. @click="addActive(index,item)">
  8. <span class="tab-bar-item_icon" :class="item.icon"></span>
  9. <span class="tab-bar-item_Text">{{item.text}}</span>
  10. </li>
  11. </ul>
  12. </div>
  13. </template>
  14. <script>
  15. export default{
  16. name:'tabbar',
  17. data (){
  18. return {
  19. isActive:this.$store.state.tabIndex,
  20. itemList:[
  21. {text:"推荐",icon:"fa fa-clipboard",link:'/'},
  22. {text:"作品",icon:"fa fa-smile-o",link:'/things'},
  23. {text:"设计师",icon:"fa fa-pencil",link:'/designer'},
  24. {text:"我",icon:"fa fa-user-o",link:'/personal'}
  25. ]
  26. }
  27. },
  28. mounted(){
  29. if(this.isActive != 0){
  30. this.$router.push(this.itemList[this.isActive].link);
  31. }
  32. },
  33. methods:{
  34. addActive: function(index,item){
  35. console.log('.....index',index)
  36. console.log('...item',item.link)
  37. this.isActive = index;
  38. this.$router.push(item.link);
  39. this.$store.commit("changeTab",index);
  40. }
  41. }
  42. };
  43. </script>
  1. //swiper.vue
  2. <template>
  3. <div class="swiper-box">
  4. <swiper :options="swiperOption" ref="swiper" >
  5. <swiper-slide v-for="(data, index) in dataList"
  6. :key="index"
  7. :class="{active: activeIndex == index}">
  8. <slot name="swiperMain" :data="data">{{data.text}}</slot>
  9. </swiper-slide>
  10. <div class="swiper-pagination" slot="pagination"></div>
  11. </swiper>
  12. </div>
  13. </template>
  14. <script>
  15. import 'swiper/dist/css/swiper.css'
  16. import { swiper, swiperSlide} from 'vue-awesome-swiper'
  17. export default{
  18. name: 'appnav',
  19. props:{
  20. activeIndex:{},
  21. swiperOption:{
  22. type:Object
  23. },
  24. dataList:{}
  25. },
  26. components:{
  27. swiper,
  28. swiperSlide
  29. }
  30. };
  31. </script>
  1. //toast.vue
  2. <template>
  3. <transition name="toast-fade">
  4. <div class="toast" v-show="visible" >
  5. <div class="toast-content">{{message}}</div>
  6. </div>
  7. </transition>
  8. </template>
  9. <script>
  10. export default {
  11. name:'toast',
  12. data(){
  13. return {
  14. visible:false,
  15. message:''
  16. }
  17. }
  18. }
  19. </script>
  1. //main.js
  2. import Vue from 'vue'
  3. import App from './App'
  4. import router from './router'
  5. import axios from 'axios'
  6. import store from './store'
  7. import scroller from 'vue-scroller'
  8. import 'font-awesome/scss/font-awesome.scss'
  9. import './assets/style/reset.css'
  10. import './assets/style/style.scss'
  11. import tabbar from './components/tabBar'
  12. import swiper from './components/swiper'
  13. import toast from './components/toast'
  14. Vue.config.productionTip = false
  15. Vue.config.devtools = true
  16. Vue.prototype.$axios = axios;
  17. Vue.use(scroller)
  18. Vue.use(tabbar)
  19. Vue.use(swiper)
  20. Vue.use(toast)
  21. new Vue({
  22. router,
  23. store,
  24. components: { App },
  25. render: h => h(App),
  26. }).$mount("#app");

接下来我们结合router来看页面

  1. //src\pages\pageView.vue
  2. <template>
  3. <div class="page-view">
  4. <transition :name="transitionName">
  5. <router-view class="child-view"></router-view>
  6. </transition>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. name:"pageView",
  12. data() {
  13. return {
  14. transitionName:'slide-left'
  15. }
  16. },
  17. watch:{
  18. $route: function(to,from){
  19. console.log('what is to',to)
  20. console.log('what is from',from)
  21. let isBack = this.$router.isBack;
  22. if(isBack){
  23. this.transitionName = 'slide-right';
  24. }else{
  25. this.transitionName = 'slide-left';
  26. }
  27. this.$router.isBack = false;
  28. },
  29. }
  30. }/* */
  31. </script>
  1. //src\pages\pageView.vue
  2. <template>
  3. <div class="tab-bar">
  4. <ul>
  5. <li v-for="(item,index) in itemList"
  6. :key="index" class="tab-bar-item"
  7. :class="{active: index == isActive}"
  8. @click="addActive(index,item)">
  9. <span class="tab-bar-item_icon" :class="item.icon"></span>
  10. <span class="tab-bar-item_Text">{{item.text}}</span>
  11. </li>
  12. </ul>
  13. </div>
  14. </template>
  15. <script>
  16. export default{
  17. name:'tabbar',
  18. data (){
  19. return {
  20. isActive:this.$store.state.tabIndex,
  21. itemList:[
  22. {text:"推荐",icon:"fa fa-clipboard",link:'/'},
  23. {text:"作品",icon:"fa fa-smile-o",link:'/things'},
  24. {text:"设计师",icon:"fa fa-pencil",link:'/designer'},
  25. {text:"我",icon:"fa fa-user-o",link:'/personal'}
  26. ]
  27. }
  28. },
  29. mounted(){
  30. if(this.isActive != 0){
  31. this.$router.push(this.itemList[this.isActive].link);
  32. }
  33. },
  34. methods:{
  35. addActive: function(index,item){
  36. console.log('.....index',index)
  37. console.log('...item',item.link)
  38. this.isActive = index;
  39. this.$router.push(item.link);
  40. this.$store.commit("changeTab",index);
  41. }
  42. }
  43. };
  44. </script>

效果为



代码为:

  1. <template>
  2. <div class="personal">
  3. <div class="personal-logo">
  4. <div class="logo">
  5. <span class="logo_img"><img src="/static/images/logo.jpg" alt=""></span>
  6. <span>登录</span>
  7. </div>
  8. </div>
  9. <div class="personal-main">
  10. <div class="personal-main_menu">
  11. <ul>
  12. <li><i class="fa fa-thumbs-o-up"></i><span>我推荐的</span></li>
  13. <li><i class="fa fa-heart-o"></i><span>我关注的</span></li>
  14. <li><i class="fa fa-folder-open-o"></i><span>我的作品</span></li>
  15. </ul>
  16. </div>
  17. <div class="personal-main_list">
  18. <ul>
  19. <li><i class="fa fa-bell-o"></i><span>消息中心</span><i class="fa fa-angle-right"></i></li>
  20. <li><i class="fa fa-bullhorn"></i><span>联系我</span><i class="fa fa-angle-right"></i></li>
  21. <li @click="toAbout"><i class="fa fa-meh-o"></i><span>关于</span><i class="fa fa-angle-right"></i></li>
  22. </ul>
  23. </div>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. import {prevent} from '../utils'
  29. export default{
  30. name: 'personal',
  31. mounted(){
  32. document.body.removeEventListener("touchmove",prevent);
  33. },
  34. methods: {
  35. toAbout:function(){
  36. this.$router.push("/about");
  37. }
  38. }
  39. };
  40. </script>

  1. //src\pages\about.vue
  2. <template>
  3. <div class="about">
  4. <div class="page-title">
  5. <span @click="goBack" class="goBack"><i class="fa fa-2x fa-angle-left"></i></span>
  6. <h3>关于</h3>
  7. </div>
  8. <div class="main">
  9. <p>声明:这只是一个练习的demo :( </p>
  10. </div>
  11. </div>
  12. </template>
  13. <script>
  14. export default{
  15. name: '',
  16. data (){
  17. return{
  18. desc:''
  19. }
  20. },
  21. methods: {
  22. goBack: function(){
  23. this.$router.goBack();
  24. }
  25. }
  26. };
  27. </script>

  1. //src\pages\things.vue
  2. <template>
  3. <div class="things">
  4. <div class="things-nav">
  5. <swiper :dataList="navList" :activeIndex="activeIndex" ref="navSwiper" :swiperOption="swiperOptionNav" ></swiper>
  6. </div>
  7. <div class="things-main">
  8. <scroller
  9. :on-refresh="refresh"
  10. :refreshText="refreshText" ref="scroller">
  11. <span style="width:20px;height:20px;" class="spinner" slot="refresh-spinner"></span>
  12. <div class="things-time">TODAY</div>
  13. <swiper
  14. :dataList="navList"
  15. :swiperOption="swiperOptionMain" ref="mainSwiper">
  16. <div slot="swiperMain" slot-scope="slotProps">
  17. <div v-for="(item, index) in slotProps.data.dataList" :key="index" class="things-item" >
  18. <div class="things-img-wrapper" @click="showDetails(item.id)">
  19. <img class="things-item_img" :src="item.img" alt="">
  20. <span class="things-item_tips">{{item.author}}</span>
  21. </div>
  22. <div class="things-item-foot">
  23. <div class="foot-desc">
  24. <span class="foot-desc_logo"><img :src="item.icon" alt=""></span>
  25. <div class="foot-desc_text">
  26. <p>{{item.author}}</p>
  27. <p class="origin">{{item.origin}}</p>
  28. </div>
  29. </div>
  30. <div class="foot-action">
  31. <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>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. </swiper>
  37. </scroller>
  38. <div class="to-top" @click="toTop"><i class="fa fa-arrow-up"></i></div>
  39. </div>
  40. </div>
  41. </template>
  42. <script>
  43. import { mixin,pageAct } from '../utils'
  44. export default{
  45. name: 'things',
  46. data (){
  47. return{
  48. likeNum:0,
  49. dislikeNum:0,
  50. }
  51. },
  52. mixins:[mixin,pageAct],
  53. methods:{
  54. showDetails: function(index){
  55. this.$router.push("/comment/"+index);
  56. },
  57. getData: function(cb){
  58. var self = this;
  59. this.$axios.post("/things",{}).then(function(response){
  60. console.log('aaaaa...',response)
  61. var result = response.data;
  62. if(result.code == 200){
  63. self.navList = result.list;
  64. }
  65. }).catch(function(error){
  66. console.log(error);
  67. });
  68. },
  69. loadMore: function(cb){
  70. var self = this;
  71. this.$axios.post("/things",{author:self.activeIndex}).then(function(response){
  72. var result = response.data;
  73. cb && cb(result);
  74. }).catch(function(error){
  75. console.log(error);
  76. });
  77. }
  78. }
  79. };
  80. </script>

  1. //src\pages\designer.vue
  2. <template>
  3. <div class="designer">
  4. <div class="designer-nav">
  5. <swiper :dataList="navList" :activeIndex="activeIndex" ref="navSwiper" :swiperOption="swiperOptionNav" ></swiper>
  6. </div>
  7. <div class="designer-main">
  8. <keep-alive>
  9. <scroller :on-refresh="refresh" :refreshText="refreshText" ref="scroller">
  10. <span style="width:20px;height:20px;" class="spinner" slot="refresh-spinner"></span>
  11. <div class="designer-time">TODAY</div>
  12. <swiper :dataList="navList" ref="mainSwiper" :swiperOption="swiperOptionMain">
  13. <div slot="swiperMain" slot-scope="slotProps">
  14. <div v-for="(item, index) in slotProps.data.dataList" :key="index" class="designer-item" >
  15. <div class="designer-img-wrapper" @click="showDetails(item.id)">
  16. <img class="designer-item_img" :src="item.img" alt="">
  17. <span class="foot-desc_logo"><img :src="item.icon" alt=""></span>
  18. </div>
  19. <div class="designer-item-foot">
  20. <div class="foot-desc">
  21. <div class="foot-desc_text">
  22. <p>{{item.author}} | <span class="origin">{{item.origin}}</span></p>
  23. </div>
  24. </div>
  25. <div class="foot-action">
  26. <span @click="showTotast" class="foot-actionr_follow">+ 关注</span>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. </swiper>
  32. </scroller>
  33. </keep-alive>
  34. <div class="to-top" @click="toTop">
  35. <i class="fa fa-arrow-up"></i>
  36. </div>
  37. </div>
  38. </div>
  39. </template>
  40. <script>
  41. import {pageAct} from '../utils'
  42. export default{
  43. name: 'designer',
  44. mixins:[pageAct],
  45. methods:{
  46. showDetails: function(index){
  47. this.$router.push("/details/"+index);
  48. },
  49. getData: function(cb){
  50. var self = this;
  51. this.$axios.post("/designer",{}).then(function(response){
  52. console.log('designer',response)
  53. var result = response.data;
  54. if(result.code == 200){
  55. self.navList = result.list;
  56. }
  57. }).catch(function(error){
  58. console.log(error);
  59. });
  60. },
  61. loadMore: function(cb){
  62. var self = this;
  63. this.$axios.post("/designer",{author:self.activeIndex}).then(function(response){
  64. var result = response.data;
  65. cb && cb(result);
  66. }).catch(function(error){
  67. console.log(error);
  68. });
  69. },
  70. showTotast: function(){
  71. this.$toast({message:"敬请期待关注功能 :-)"});
  72. }
  73. }
  74. };
  75. </script>

  1. //src\pages\details.vue
  2. <template>
  3. <div class="things-details" >
  4. <div class="page-title">
  5. <span @click="goBack" class="goBack"><i class="fa fa-2x fa-arrow-circle-left"></i></span>
  6. <h3>{{title}}</h3>
  7. </div>
  8. <div class="details-main">
  9. <div class="img-box">
  10. <img :src="img" alt="">
  11. </div>
  12. <div class="things-label">简介</div>
  13. <div class="things-desc">
  14. <div class="desc-item" v-for="(item, index) in descList" :key="index">
  15. <span class="desc-item_icon fl"><i class="fa" :class="item.icon"></i></span>
  16. <div class="desc-item_text"><em>{{item.tips}}:</em><p>{{item.text}}</p></div>
  17. </div>
  18. </div>
  19. <div class="things-label">其他作品</div>
  20. <div class="desc-img-box clearfix">
  21. <div class="desc-img-item" v-for="(item, index) in imgList" :key="index">
  22. <div class="img-item_text">—{{item.originate}}—</div>
  23. <div class="desc-item_img"><img :src="item.img" alt=""></div>
  24. </div>
  25. </div>
  26. <p class="page-footer">—— 没有了呢 ——</p>
  27. </div>
  28. </div>
  29. </template>
  30. <script>
  31. import {prevent,goBack} from '../utils/index.js'
  32. export default{
  33. name: 'thing-details',
  34. mixins:[goBack],
  35. data() {
  36. return {
  37. id:'',
  38. title:'',
  39. img:'',
  40. descList:[
  41. {icon:'fa-paint-brush',tips:"派系",text:''},
  42. {icon:'fa-map-o',tips:"代表作",text:''},
  43. {icon:'fa-newspaper-o',tips:"简介",text:''}
  44. ],
  45. imgList:[]
  46. }
  47. },
  48. created(){
  49. this.id = this.$route.params.id;
  50. this.loadMore();
  51. },
  52. mounted(){
  53. this.id = this.$route.params.id;
  54. document.body.removeEventListener("touchmove",prevent);
  55. document.body.addEventListener("touchmove",function(){
  56. },{passive: true});
  57. },
  58. methods:{
  59. loadMore: function(cb){
  60. var self = this;
  61. this.$axios.post("/designer",{id:self.id}).then(function(response){
  62. var result = response.data;
  63. if(result.code == 200){
  64. self.title = result.list.title;
  65. self.img = result.list.portrait;
  66. self.descList[0].text = result.list.genre;
  67. self.descList[1].text = result.list.magnumOpus;
  68. self.descList[2].text = result.list.desc;
  69. self.imgList = result.list.arts;
  70. }
  71. }).catch(function(error){
  72. console.log(error);
  73. });
  74. }
  75. }
  76. }
  77. </script>
  78. ```vue
  79. //src\pages\comment.vue
  80. <template>
  81. <div class="comment" >
  82. <div class="page-title">
  83. <span @click="goBack" class="goBack"><i class="fa fa-2x fa-arrow-circle-left"></i></span>
  84. <h3>{{title}}</h3>
  85. </div>
  86. <div class="comment-main">
  87. <div class="comment-main_img">
  88. <swiper :dataList="imgList" ref="imgSwiper" :swiperOption="swiperOptionImg" >
  89. <div slot="swiperMain" slot-scope="slotProps">
  90. <img class="comment-item_img" :src="slotProps.data.img" alt="">
  91. </div>
  92. </swiper>
  93. </div>
  94. <div class="comment-act">
  95. <span @click="like" class="fa fa-meh-o action-up"></span><span v-show="likeNum" class="comment-act__like"><i>+{{likeNum}}</i></span> ||
  96. <span @click="dislike" class="fa fa-frown-o action-down"></span><span v-show="dislikeNum" class="comment-act__dislike"><i>{{dislikeNum}}</i></span>
  97. </div>
  98. <div class="comment-desc">
  99. <div class="desc-item" v-for="(item, index) in descList" :key="index">
  100. <span class="desc-item_icon fl"><i class="fa" :class="item.icon"></i></span>
  101. <div class="desc-item_text"><em>{{item.tips}}:</em><p>{{item.text}}</p></div>
  102. </div>
  103. </div>
  104. <div class="comment-designer-desc">
  105. <span class="comment-desc-icon"><img :src="icon" alt=""></span>
  106. <h3 class="comment-desc-designer" >{{title}}</h3>
  107. <span @click="showTotast" class="foot-actionr_follow">+ 关注</span>
  108. <div class="desc-item_text"><p>{{designer}}</p></div>
  109. </div>
  110. <div class="comment-designer-word clearfix">
  111. <div class="img fr">
  112. <img :src="wordImg" alt="">
  113. </div>
  114. <div class="word">
  115. <h4>我同疯子的唯一区别,在于我不是疯子。我同人类的唯一区别,在于我是疯子</h4>
  116. <p>——达利</p>
  117. </div>
  118. </div>
  119. <div class="comment-list">
  120. <span class="comment-list-tips">评论({{cNum}})</span>
  121. <div class="list">
  122. <ul>
  123. <li v-for="(item,index) in commentList" :key="index">
  124. <span class="comment-user_logo fl"><img :src="item.icon" alt=""></span>
  125. <div class="comment-content">
  126. <p class="user-name">{{item.name}}:</p>
  127. <p class="user-time">{{item.time}}</p>
  128. <p class="user-word">{{item.content}}</p>
  129. </div>
  130. </li>
  131. </ul>
  132. </div>
  133. <p class="page-footer">—— 没有了呢 ——</p>
  134. </div>
  135. </div>
  136. <div class="comment-area" >
  137. <span class="icon"><img :src="icon" alt=""></span>
  138. <input class="send-input" type="text" placeholder="留下爪印" v-model="sendMsg" @focus="setPosition">
  139. <input type="button" class="send-btn" value="评论" @click="send">
  140. </div>
  141. <transition name="slide-fade">
  142. <div class="showNew" v-show="showNew">
  143. 最新评论:{{commentList[0].content}}
  144. </div>
  145. </transition>
  146. </div>
  147. </template>
  148. <script>
  149. import {prevent,mixin} from '../utils'
  150. export default{
  151. name: 'comment-details',
  152. mixins:[mixin],
  153. data() {
  154. return {
  155. id:'',
  156. title:'',
  157. img:'',
  158. icon:'',
  159. wordImg:'',
  160. likeNum:0,
  161. dislikeNum:0,
  162. swiperOptionImg:{
  163. autoplay:true,
  164. loop :true,
  165. pagination: {
  166. el: '.swiper-pagination',
  167. dynamicBullets: true
  168. }
  169. },
  170. designer:'',
  171. descList:[
  172. {icon:'fa-paint-brush',tips:"派系",text:''},
  173. {icon:'fa-map-o',tips:"代表作",text:''}
  174. ],
  175. imgList:[],
  176. commentList:[
  177. {icon:'./static/images/logo.jpg',name:'路人甲',time:'2018-10-01 12:12:12',content:'这是一条评论'},
  178. {icon:'./static/images/logo.jpg',name:'路人甲',time:'2018-10-01 12:12:12',content:'这是另外一条评论'},
  179. {icon:'./static/images/logo.jpg',name:'路人甲',time:'2018-10-01 12:12:12',content:'这是一条长长长长长长长长长长长长长长长长长长长长长长长长长长长的评论'},
  180. ],
  181. cNum:3,
  182. sendMsg:'',
  183. showNew:false
  184. }
  185. },
  186. created(){
  187. this.id = this.$route.params.id;
  188. this.loadData();
  189. },
  190. mounted(){
  191. this.id = this.$route.params.id;
  192. document.body.removeEventListener("touchmove",prevent);
  193. },
  194. watch:{
  195. showNew: function(){
  196. var self = this;
  197. setTimeout(function(){
  198. self.showNew = false;
  199. },1000);
  200. }
  201. },
  202. methods:{
  203. loadData: function(cb){
  204. var self = this;
  205. this.$axios.post("/designer",{id:self.id}).then(function(response){
  206. var result = response.data;
  207. if(result.code == 200){
  208. self.title = (result.list.title).split("/")[0];
  209. self.icon = result.list.icon;
  210. self.img = result.list.portrait;
  211. self.descList[0].text = result.list.genre;
  212. self.descList[1].text = result.list.magnumOpus;
  213. self.designer = result.list.desc;
  214. self.imgList = result.list.arts;
  215. self.wordImg = result.list.arts[0].img;
  216. }
  217. }).catch(function(error){
  218. console.log(error);
  219. });
  220. },
  221. send: function(){
  222. if(this.sendMsg){
  223. this.commentList.unshift({
  224. icon:'./static/images/logo.jpg',name:'路人乙',time:'刚刚',content:this.sendMsg
  225. });
  226. this.cNum ++;
  227. this.showNew = true;
  228. this.sendMsg = '';
  229. }
  230. },
  231. setPosition: function(){
  232. // 解决安卓手机输入时键盘弹起遮盖输入框的问题
  233. document.querySelector(".page-footer").scrollIntoView(true);
  234. }
  235. }
  236. }
  237. </script>

  1. //src\pages\pictoral.vue
  2. // 这个是对进入页面的动画的处理
  3. <template>
  4. <div class="pictoral">
  5. <div class="pictoral-main">
  6. <transition-group name="cell" tag="div" class="container"
  7. v-bind:css="false"
  8. v-on:before-enter="beforeEnter"
  9. v-on:enter="enter"
  10. v-on:leave="leave">
  11. <div v-for="(data, index) in dataList" class="pictoral-item"
  12. :key="index"
  13. :data-index="index" >
  14. <span class="pictoral-item_logo"><img :src="data.icon" alt=""></span>
  15. <h6>{{data.title}}</h6>
  16. <p>——{{data.originate}}</p>
  17. <img :src="data.img" alt="">
  18. <p>{{data.desc}}</p>
  19. </div>
  20. </transition-group>
  21. <div class="no-more-data" v-show="noData"><i class="fa fa-hand-o-up"></i><p>没有更多了,试试向上滑动吧!</p></div>
  22. </div>
  23. </div>
  24. </template>
  25. <script>
  26. import AlloyFinger from 'alloyfinger'
  27. import Velocity from 'velocity-animate/velocity.js'
  28. import 'velocity-animate/velocity.ui.js'
  29. import {prevent} from '../utils'
  30. export default{
  31. name: 'pictoral',
  32. data (){
  33. return{
  34. dataList:[],
  35. first:0,
  36. second:1,
  37. third:2,
  38. forth:3,
  39. slideStart:0,
  40. slideEnd:0,
  41. activeIndex:0,
  42. stop:false,
  43. noData:false
  44. }
  45. },
  46. created: function(){
  47. this.getData();
  48. },
  49. mounted: function(){
  50. this.bindSlide();
  51. document.body.addEventListener("touchmove",prevent);
  52. },
  53. watch:{
  54. activeIndex:function(){
  55. var list = document.querySelectorAll(".pictoral-item");
  56. this.stop = true;
  57. for(var i=0;i < list.length;i++){
  58. this.leave(list[i]);
  59. }
  60. if(this.activeIndex == this.dataList.length){
  61. this.noData = true;
  62. }else{
  63. this.noData = false;
  64. }
  65. },
  66. slideEnd: function(){
  67. if(!this.stop){
  68. if(this.slideEnd - this.slideStart > 20){
  69. if(!this.noData){
  70. this.first += 1;
  71. this.second += 1;
  72. this.third += 1;
  73. this.forth += 1;
  74. this.activeIndex++;
  75. }
  76. }else if(this.slideEnd - this.slideStart < -20){
  77. if(this.first > 0){
  78. this.first -= 1;
  79. this.second -= 1;
  80. this.third -= 1;
  81. this.forth -= 1;
  82. this.activeIndex--;
  83. }
  84. }
  85. }
  86. }
  87. },
  88. methods:{
  89. beforeEnter: function (el) {
  90. el.style.opacity = 0;
  91. el.style.height = 0;
  92. },
  93. enter: function (el, done) {
  94. var delay = el.dataset.index * 50;
  95. var top = '';
  96. var width = this.setWidth(el.dataset.index);
  97. if(el.dataset.index >= (this.first + 4)){
  98. top = 15 + "%";
  99. }else{
  100. top = (4 - (el.dataset.index - this.first))*8 + "%";
  101. }
  102. setTimeout(function () {
  103. Velocity(
  104. el,
  105. { opacity: 1,
  106. height: '80%',
  107. translateY:top,
  108. width:width,
  109. zIndex: 1000 - el.dataset.index
  110. },
  111. { complete: done }
  112. )
  113. }, delay);
  114. },
  115. leave: function (el, done) {
  116. var self = this;
  117. var top = '';
  118. var delay = el.dataset.index * 10;
  119. var width = this.setWidth(el.dataset.index);
  120. if(el.dataset.index < this.first){
  121. top = "99%";
  122. }else{
  123. if(el.dataset.index >= (this.first + 4)){
  124. top = 15 + "%";
  125. }else{
  126. top = (4 - (el.dataset.index - this.first))*10 + "%";
  127. }
  128. }
  129. Velocity(
  130. el,
  131. {
  132. width:width,
  133. translateY:top
  134. },{
  135. mobileHA:true,
  136. easing: [ 0.4, 0.01, 0.165, 0.99 ],
  137. complete: function(){
  138. if(el.dataset.index == (self.dataList.length - 1)){
  139. self.stop = false;
  140. }
  141. }
  142. }
  143. );
  144. },
  145. bindSlide: function(){
  146. var self = this;
  147. var el = document.querySelector(".pictoral-main");
  148. var fl = new AlloyFinger(el,{
  149. touchStart: function(evt){
  150. self.slideStart = evt.changedTouches[0].clientY;
  151. },
  152. touchMove: function(evt){
  153. self.slideEnd = evt.changedTouches[0].clientY;
  154. },
  155. touchEnd:function (evt) {
  156. self.slideEnd = evt.changedTouches[0].clientY;
  157. }
  158. });
  159. },
  160. setWidth: function(index){
  161. return index == this.first ? '76%' :
  162. index == this.second ? '68%' :
  163. index == this.third ? '56%' : '40%';
  164. },
  165. getData: function(){
  166. var self = this;
  167. this.$axios.post("/pictoral",{}).then(function(response){
  168. var result = response.data;
  169. if(result.code == 200){
  170. self.dataList =self.dataList = result.list;
  171. }
  172. }).catch(function(error){
  173. console.log(error);
  174. });
  175. }
  176. }
  177. };
  178. </script>

昏昏欲睡

【vue】imitate-beautiful-thing的更多相关文章

  1. 【Vue】Vue中的父子组件通讯以及使用sync同步父子组件数据

    前言: 之前写过一篇文章<在不同场景下Vue组件间的数据交流>,但现在来看,其中关于“父子组件通信”的介绍仍有诸多缺漏或者不当之处, 正好这几天学习了关于用sync修饰符做父子组件数据双向 ...

  2. 【vue】移动端demo资料

    http://imzjh.com/inew/#/(移动端demo) https://github.com/liangxiaojuan/eleme(饿了么git地址) https://github.co ...

  3. 【vue】MongoDB+Nodejs+express+Vue后台管理项目Demo

    ¶项目分析 一个完整的网站服务架构,包括:   1.web frame ---这里应用express框架   2.web server ---这里应用nodejs   3.Database ---这里 ...

  4. 【vue】本地开发mock数据支持

    项目离不开数据渲染的支持,为本地开发配置 数据  支持. (一)方式一:安装JSON Server搭建mock数据的服务器 json Server 是一个创建 伪RESTful服务器的工具. 配置流程 ...

  5. 【vue】npm run mock & npm run dev 无法同时运行的解决

    [关于系统,没注明的都是windows系统,若以后用的是mac系统则会另外备注] 当项目数据是通过mock搭建而成(参照:[vue]本地开发mock数据支持)时,运行mock服务器和项目的命令 就参照 ...

  6. 【VUE】自定义组件

    [VUE]自定义组件 转载: ============================================ ======================================== ...

  7. 【VUE】使用问题记录

    [VUE]使用问题记录 ===================================================================== 1.Vue.nextTick 修改数 ...

  8. 【VUE】数组

    [VUE]常用函数 转载:https://www.cnblogs.com/yangchongxing/p/10637087.html 目录 ============================== ...

  9. 【题解】P4755 Beautiful Pair(启发式合并的思路+分治=启发式分治)

    [题解]P4755 Beautiful Pair upd: 之前一个first second烦了,现在AC了 由于之前是直接抄std写的,所以没有什么心得体会,今天自己写写发现 不知道为啥\(90\) ...

  10. 【vue】生成接口模拟数据

    目录 方案一:自定义模拟数据 Step1 创建json文件 Step2 在 vue.config.js 中配置 Step3 在组件中使用 (方式一) Step3 封装api (方式二) Step4 在 ...

随机推荐

  1. Spring父子上下文(WebApplicationContext)(防止事务失效)

    如果你使用了listener监听器来加载配置,一般在Struts+Spring+Hibernate的项目中都是使用listener监听器的.如下 <listener> <listen ...

  2. 【默默努力】ig-wxz-and-hotdog

    这个是一个非常跟热点的小游戏,思聪吃热狗.这个游戏的话,我感觉思路还挺简单的,天上会掉热狗和障碍物, 思聪在下面张开嘴巴,进行左右移动,接热狗.如果吃到的是热狗就得一分,如果思聪吃到的不是热狗,是障碍 ...

  3. 看 《android权威编程指南》 的笔记

    Android 编译工具 确保ant已安装并正常运行,android sdk的tools/和platform-tools目录包含在可执行文件的搜索路径中 切换到项目目录并执行以下命令: android ...

  4. [转]使用TortoiseGit处理代码冲突

    场景一  user0 有新提交 user1 没有pull -> 写新代码 -> pull -> 提示有冲突   解决办法一 -> stash save(把自己的代码隐藏存起来) ...

  5. Spring Cache 简介

    org.springframework.cache; org.springframework.cache.Cache org.springframework.cache.CacheManager 依赖 ...

  6. 数据结构学习笔记_树(二叉搜索树,B-树,B+树,B*树)

    一.查找二叉树(二叉搜索树BST) 1.查找二叉树的性质 1).所有非叶子结点至多拥有两个儿子(Left和Right): 2).所有结点存储一个关键字: 3).非叶子结点的左指针指向小于其关键字的子树 ...

  7. 阿里云全站加速DCDN全面支持WebSocket协议

    WebSocket协议可以为网站和应用提供真正的双向通信,具有控制开销.保持连接状态.更强实时性.更好的压缩效果等优点,是当下低延时应用最常采用的一种技术协议.为了更好的满足客户在实时通讯场景下的加速 ...

  8. iframe跨域数据传递

    项目中需要和其他单位合作开发,方案采用iframe嵌入页面,开发过程中设计到了跨域数据的传递,初步方案决定使用html5 API postMessage进行iframe跨域数据传递: 域名A下的页面 ...

  9. System.Web.Mvc.FilePathResult.cs

    ylbtech-System.Web.Mvc.FilePathResult.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, Pub ...

  10. 转:五种I/O模型和select函数简介

    源地址:http://blog.csdn.net/jnu_simba/article/details/9070955 一.五种I/O模型 1.阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调 ...