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>
<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>