vue+mongoose+node.js項目總結第四篇_實現左右滑動功能

1、前言                                                                              css

下面這個功能也是比較常見的一個炫酷的功能,vue配合移動端滑動事件實現左右滑動的效果html

 

 

 

 

2、主要內容                                                                       vue

1.第一步:組件準備git

 

 

 

導航條使用的是一個公共組件NavBar.vuegithub

 

 

 

2.第二步:router中的路由配置,將切換的路由添加到router裏面vuex

 

 

 

3.第三步:由於項目中須要用到v-touch因此須要安裝v-touchnpm

                 (1)參考文檔:https://github.com/vuejs/vue-touch/tree/next數組

                 (2)須要注意的是vue2.0以後須要用到next分支才行app

          

 

 

             (3)安裝:npm insall vue-touch@next --saveide

             (4)在腳手架中的main.js中引入:

import VueTouch from 'vue-touch'
Vue.use(VueTouch, {name: 'v-touch'})

             (5)使用:

 

 

 

4.具體實現

4.1點擊上面的導航條實現切換

(1)將導航條上的item分類數組傳到NavBar.vue組件中

 

 

 

(2)在NavBar.vue組件中須要完成如下幾個功能

        NavBar.vue-事件1: 組件建立以後設置左右滾動的輪播圖

        NavBar.vue-事件2:默認應該讓第一個高亮

        NavBar.vue-事件3:點擊切換時高亮改變爲當前點擊的,而且下面的子組件跟隨改變

 

 NavBar.vue-事件1:組件建立以後設置左右滾動的輪播圖,而且默認第一個高亮

 

 

 

  NavBar.vue-事件2:在NavBar.vue中點擊,在index.vue中切換

 

 

 

 

 

 

在index.vue中監聽到NavBar.vue中傳到state中的navState實現切換功能

 computed: {
   //獲取到從NavBar.vue點擊的時候保存的當前項的下標
    getNavState () {
      return this.$store.state.navState
    }
  },
  watch: {//監聽當前項的下標,一旦有變化就切換路由
    // 監聽計算屬性 而且它來自vuex中狀態
    getNavState(state){
      var index = state + 1 
      // 跳轉子頁面 this.$router.push()
      this.$router.push('/index/page' + index)
    }
}

 

4.2滑動的時候實現切換

(1)滑動的事件是在index.vue組件中,須要完成以下幾個事件

             index.vue事件1:用戶左右滑動

             index.vue事件2:上面的導航會根據滑動到當前的地方,在當前的nav item顯示高亮

             index.vue事件3:滑動的加上滑動的動畫

index.vue事件1:向左右滑動的事件

onSwipeleft () {
      let index = 1 //默認index爲1,顯示第一個page
      let next = ""
      if(this.$route.name != null) { //子路由"pagex",若是子路由不爲空
        index =  +this.$route.name[4]//將this.$route.name[4]轉化爲數字
       //若是當前的index<頁面最大的標號,表示能夠向左滑動,修改滑動的路由,
        index < 8  ?  (next = "page" + (index + 1)) &&(this.chooseItem = index + 1) && (this.chooseItem = +index + 1)
       : (next="page8") && (this.chooseItem = 7)
       this.$router.push('/index/' + next)
      } 
    },
    onSwipeRight () {
      // this.$router.back(-1)
      let index = 1
      let back = ""
      if(this.$route.name != null) {
        index =  +this.$route.name[4]
        index > 1  ?  (back = "page" + (index - 1)) &&(this.chooseItem = index - 1) && (this.chooseItem = +index - 1)
       : (back="page1") && (this.chooseItem = 1)
       this.$router.push('/index/' + back)
      } else {
        this.$router.push('/index/' + "page6")
      }
      
    } 

 

 index.vue事件3:滑動的加上滑動的動畫, 添加滑動動畫須要監聽route的改變

 

使用vue中的transition包裹路由組件出口

參考資料:https://cn.vuejs.org/v2/guide/transitions.html#%E8%BF%87%E6%B8%A1%E7%9A%84%E7%B1%BB%E5%90%8D

 

 

 

watch中監聽route的變化,判斷是應該作向右滑動的動畫仍是向左滑動的動畫

 '$route' (to, from) {
      console.log(to.path.split('/')) 
      let toNum = to.path.split('/')[2] //[index, pagex]
      console.log(toNum)//目的子路由
      let fromNum = from.path.split('/')[2]
      console.log(fromNum)//開始子路由
      if (toNum > fromNum) {//
        this.transitionName = 'slide-left' //目的子路由>開始子路由 向左滾動
      } else {
        this.transitionName = 'slide-right'//在向右滾動
      }
    }

 

style裏面爲了實現過渡效果定義的動畫以下所示:

 .Router{
    width: 100%;
    transition: all .4s ease;
  }

  .slide-left-enter, .slide-right-leave-active{
    opacity: 0;
    transform: translateX(100%);
  }

  .slide-left-leave-active, .slide-right-enter{
    opacity: 0;
    transform: translateX(-100%);
  }

 

(3)滑動的時候上面導航欄也要跟着高亮:直接在Navbar.vue中監聽傳來的chooseItem是否變化

 watch: {
    "chooseItem" () {
      this.chooseId = this.chooseItem-1
    }
  },

 

3、總結                                                                                          

第一部分:點擊上面的導航切換下面的自滷藕

 

 

 

 

第二部分:左右切換上面的導航跟着高亮

 

 

 

第三部分關鍵組件代碼

<template lang="html">
  <div class="page">
    <div class="header">
      <div class="left" @click="goback()">
        <i>返回</i>
      </div>
      
      <input class="search"  type="" name="" placeholder="搜你想搜的地方,過你想要的生活">
     
      <div class="right">
       
      </div>
    </div>
   
   
    <navbar :navs="navs" :chooseItem="chooseItem"></navbar>
    <v-touch @swipeleft="onSwipeleft" @swiperight="onSwipeRight" :priority="1">
      <transition :name="transitionName">
        <keep-alive>
          <router-view class="Router"></router-view>  
        </keep-alive>
      </transition>
    </v-touch>

  </div>

</template>

<script>
import navbar from '@/components/NavBar/NavBar.vue'
export default {
  data () {
    return {
      navs: ['爬山','看海','農家樂','小酒館','賞月','紅色景點','名人寒舍'],
      transitionName: 'slide-right', //默認向右滑動
      chooseItem: 0//默認顯示的是第一個page
     
    }
  },
  components: {
    navbar
  },
  computed: {
    getNavState () {
      return this.$store.state.navState
    }
  },
  watch: {
    // 監聽計算屬性 而且它來自vuex中狀態
    getNavState(state){
      var index = state + 1
      // 跳轉子頁面 this.$router.push()
      this.$router.push('/index/page' + index)
    },  
    '$route' (to, from) {
      console.log(to.path.split('/')) 
      let toNum = to.path.split('/')[2]
      console.log(toNum)//目的子路由
      let fromNum = from.path.split('/')[2]
      console.log(fromNum)//開始子路由
      if (toNum > fromNum) {//
        this.transitionName = 'slide-left' //目的子路由>開始子路由 向左滾動
      } else {
        this.transitionName = 'slide-right'
      }
    }
  },
  created () {
    // 初始化
    this.$router.push('/index/page1')
  },
  methods: {
    //返回
    goback(){
      return this.$router.push('/home')
    },
    onSwipeleft () {
      let index = 1 //默認index爲1,顯示第一個page
      let next = ""
      if(this.$route.name != null) { //子路由"pagex",若是子路由不爲空
        index =  +this.$route.name[4]//將this.$route.name[4]轉化爲數字
        index < 8  ?  (next = "page" + (index + 1)) &&(this.chooseItem = index + 1) && (this.chooseItem = +index + 1)
       : (next="page8") && (this.chooseItem = 7)
       this.$router.push('/index/' + next)
      } 
    },
    onSwipeRight () {
      // this.$router.back(-1)
      let index = 1
      let back = ""
      if(this.$route.name != null) {
        index =  +this.$route.name[4]
        index > 1  ?  (back = "page" + (index - 1)) &&(this.chooseItem = index - 1) && (this.chooseItem = +index - 1)
       : (back="page1") && (this.chooseItem = 1)
       this.$router.push('/index/' + back)
      } else {
        this.$router.push('/index/' + "page6")
      }
      
    } 

  }
}
</script>


<style type="text/css">
  .header{
    background: #1fab89;
    height: 50px;
  }
  .left{
    display: inline-block;
    margin-top: 10px;
    margin-right: 8px;
    padding-left: 10px;
  }

  .search{
    height: 30px;
    width: 280px;
    border-radius: 10px;
  }

  .Router{
    width: 100%;
    transition: all .4s ease;
  }

  .slide-left-enter, .slide-right-leave-active{
    opacity: 0;
    transform: translateX(100%);
  }

  .slide-left-leave-active, .slide-right-enter{
    opacity: 0;
    transform: translateX(-100%);
  }


</style>
Index.vue
<template lang="html">
  <div class="nav">
    <div class="nav-wrapper" ref="navWrapper">
      <ul>
        <li class="nav-item " v-for="(item,index) in navs" 
          
          @click="isActive(index)" :class="chooseId==index?'is-selected':''">{{item}}</li>
      </ul>
    </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
  data () {
    return {
      chooseId: '0',
    }
  },
  props: {
    navs: Array,//父組件中接收到的導航數組
    chooseItem: Number, 
  
  },
  created () {
    this.$nextTick(() => {
      this.navScroll = new BScroll(this.$refs.navWrapper, {
        click: true,
        scrollX: true,
        eventPassthrough: 'vertical'
      })

      this.isActive(0)
    })
  },
  methods: {
    isActive (index) {//點擊當前的將當前的item下標值傳過來
      this.chooseId = index//點擊的時候改變chooseId,若是chooseId==index就設置點擊的高亮
      this.$store.state.navState = this.chooseId//當前的item值存到vuex中給index頁面使用,
    }
  },
  
  watch: {
    "chooseItem" () {
      this.chooseId = this.chooseItem-1
    }
  },


}
</script>

<style type="text/css">
  .nav-wrapper{
    overflow: hidden;
    width: 100%;
  }

  .nav-wrapper ul{
    min-width: 118%;
    white-space: nowrap;
    margin: 5px ;

  }

  .nav-wrapper ul .nav-item{
    display: inline-block;
    font-size: 18px;
    min-width: 20px;
    color: #000;
    height: 20px;
    margin-right: 5px;
  }

  .is-selected{
    color: red;
    padding-bottom: -2px;
    border-bottom: 2px solid #fe4070;
  }
</style>
NavBar.vue
相關文章
相關標籤/搜索