Vue項目中使用better-scroll實現(xiàn)菜單映射功能方法
組件全部代碼
<template> <div class="goods"> <!--左側(cè)區(qū)域--> <div class="menu-wrapper" ref="left"> <ul class="menu"> <li class="menu-item border-bottom" :class="{'current':currentIndex===index}" v-for="(item,index) in dataLlist.goods" :key="index" @click="selectIndex(index,$event)" ref="menuList" > <div class="text"> <goods-icon v-show="item.type>0" :index="item.type" class="text-ico"></goods-icon> {{item.name}} </div> </li> </ul> </div> <!--右側(cè)區(qū)域--> <div class="foods-wrapper" ref="right"> <ul> <li class="food-list food-list-hook" v-for="(item,index) in dataLlist.goods" :key="index"> <!--標題區(qū)域--> <h1 class="border-left">{{item.name}}</h1> <ul> <li class="food-item border-bottom" v-for="(foodItem,index) in item.foods" > <div class="food-image"> <img :src="foodItem.icon" alt="foodItem.name"> </div> <div class="food-desc"> <div class="title">{{foodItem.name}}</div> <div class="desc">{{foodItem.description}}</div> <div class="num"> <div class="sellCount">月售{{foodItem.sellCount}}份</div> <div class="rating">好評率{{foodItem.rating}}%</div> </div> <div class="price"> <div class="new-price">¥{{foodItem.price}}</div> <div class="old-price border-bottom" v-show="foodItem.oldPrice">¥{{foodItem.oldPrice}}</div> </div> </div> </li> </ul> </li> </ul> </div> </div> </template> <script> import Icon from '../../common/iconType/Icon'; import BScroll from 'better-scroll' export default { name: "Goods", props:['dataLlist'], data(){ return{ listHeight:[], scrollY:0 ,//為了實現(xiàn)左右區(qū)域映射 } }, computed:{ currentIndex(){ //這個返回的是下標,當這個currentIndex的值與goods的下標一致的時候, // 左側(cè)區(qū)域就會呈現(xiàn)高亮現(xiàn)象 for (let i = 0; i < this.listHeight.length; i++) { let height1 = this.listHeight[i]; let height2 = this.listHeight[i + 1]; if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { this._followScroll(i) //實現(xiàn)當滑動的時候,左側(cè)隱藏的食物類型顯示 return i; } } return 0; } }, created(){ //dataLlist數(shù)據(jù)是異步加載,直接用new BScroll時,dom可能還沒有更新 this.$nextTick(()=>{ //this.$nextTick()將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行,使用$nextTick異步初始化Bscroll this.meunScroll=new BScroll(this.$refs.left,{ click:true }); this.foodScroll=new BScroll(this.$refs.right,{ probeType: 3 //可以派發(fā)scroll事件,檢測到實時滾動的位置 }); this.foodScroll.on('scroll',(pos) =>{ //參數(shù)pos就是在右側(cè)區(qū)域滑動的實時位置 //Math.round()取整數(shù),Math.abs取絕對值 this.scrollY =Math.abs( Math.round(pos.y)); }); this._calculateHeight(); //這個方法為了獲取每個商品類的最大區(qū)間的高度 }) }, methods:{ _followScroll(index) { if(index > 0 ){ let menuList = this.$refs.menuList; let el = menuList[index]; this.meunScroll.scrollToElement(el, 300, 0, -100);//better-scroll的scrollToElement方法滾動到指定位置 } }, _calculateHeight(){ //這個方法為了獲取每個商品類的最大區(qū)間的高度 let height = 0; let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook'); this.listHeight.push(height); //listHeight這個數(shù)組是用來存放右側(cè)商品中每個類型商品的最大區(qū)間高度的集合 for(var i=0;i<foodLsit.length;i++){ let item = foodLsit[i]; //clientHeight代表元素的高度 height += item.clientHeight; //每個元素的高度等于自身高度加上上一個元素的高度 this.listHeight.push(height); //最終listHeight集合了所有l(wèi)i[類為food-list-hook]到最頂部的高度 } }, selectIndex(index,ele){ //better-scroll 會禁止移動端的點擊事件,需要重新派發(fā),同時在PC端會點擊兩次,此處需要做判斷 if(!ele._constructed){ //better-scroll的派發(fā)事件scroll的event和pc端瀏覽器的點擊事件的event有個 // 屬性區(qū)別_constructed,pc端瀏覽器的點擊事件的event中是沒有這個屬性的 return; } let rightItem =this.$refs.right.getElementsByClassName('food-list-hook'); let item = rightItem[index]; //找到相應(yīng)的li this.foodScroll.scrollToElement(item, 250) //better-scroll的scrollToElement方法滾動到指定位置 } // scrollToElement(el, time, offsetX, offsetY, easing) //第一個值接收目標元素,第二個是滾動時間,第三第四個是相對于目標元素的偏移量。 }, components:{ 'goods-icon': Icon } } </script> <style scoped lang="stylus"> @import "../../assets/stylus/mixin.styl" .goods position absolute top 3.6rem bottom .92rem display flex width: 100% overflow: hidden .menu-wrapper flex 0 0 1.6rem width 1.6rem background-color #f3f5f7 .menu-item height 1.08rem display flex align-items center justify-content left &.border-bottom::before color rgba(7,17,27,.1) .text font-weight 200 font-size .24rem line-height .28rem margin 0 .24rem .text-ico margin-right -.08rem vertical-align top; &.current font-size .24rem line-height .28rem color rgb(240,20,20) background-color #ffffff .foods-wrapper flex 1 .food-list h1 width 100% height .52rem line-height .52rem padding-left .28rem background-color #f3f5f7 font-size .24rem color rgb(147,153,159) &.border-left::before border-color #d9dde1 border-width .1rem .food-item display flex padding .36rem &:last-child.border-bottom border none .food-desc margin-left .2rem font-size .2rem color rgb(147,153,159) .title font-size:.28rem color rgb(7,17,27) margin-top .04rem line-height .28rem .desc margin .15rem auto line-height:.28rem .num display flex margin 0 0 .16rem 0 .sellCount margin-right .24rem .price display flex align-items center .new-price color rgb(220,20,60) font-weight 700 line-height .48rem margin-right .16rem font-size .28rem .old-price &.border-bottom::before position absolute top: 25%; border-width: 0.08rem; </style>
Vue項目中使用better-scroll實現(xiàn)菜單滑動功能
安裝和在組件中引入better-scroll
npm install better-scroll --save
引入import BScroll from 'better-scroll' 【在組件中引入,在后續(xù)的export default中就可以直接使用封裝好的better-scroll功能了】
better-scroll實現(xiàn)的下面功能
在菜單中要實現(xiàn)點擊左側(cè)菜單的食品類型名稱,右側(cè)就會自動滑動到此食品類型下的所有食品;在右側(cè)區(qū)域中滑動到食品類型下的所有食品區(qū)域下的時候,左側(cè)菜單會出現(xiàn)相應(yīng)的高亮效果
如何實現(xiàn)上面的功能:
第一:需要知道要在哪些區(qū)域間實現(xiàn)滑動
第二:通過new BScroll()獲取要實現(xiàn)滑動的區(qū)域
this.meunScroll=new BScroll(this.$refs.left); this.foodScroll=new BScroll(this.$refs.right);
第三:上面代碼在理論上應(yīng)該在相應(yīng)的區(qū)域都應(yīng)該能滑動了,但是現(xiàn)實是并不能滑動
原因是:數(shù)據(jù)的獲取是異步獲取的,在定義滑動區(qū)域的時候,也許數(shù)據(jù)還沒有更新,這是this.meunScroll的高度可能就沒有高度外部類goods的高度,這樣就不會滑動。
解決的方法:this.$nextTick()將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行,使用$nextTick異步初始化Bscroll
this.$nextTick(()=>{ //this.$nextTick()將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行,使用$nextTick異步初始化Bscroll this.meunScroll=new BScroll(this.$refs.left,{ click:true //左側(cè)菜單可以進行點擊事件 }); this.foodScroll=new BScroll(this.$refs.right,{ probeType: 3 //可以派發(fā)scroll事件,檢測到實時滾動的位置 }); 【this.foodScroll中必須有 probeType: 3后才能進行下面的scroll事件】 this.foodScroll.on('scroll',(pos) =>{ //參數(shù)pos就是在右側(cè)區(qū)域滑動的實時位置 //Math.round()取整數(shù),Math.abs取絕對值 this.scrollY =Math.abs( Math.round(pos.y)); }); this._calculateHeight(); //這個方法為了獲取每個商品類的最大區(qū)間的高度 })
獲取每個右側(cè)區(qū)域的 <li class="food-list food-list-hook">的高度
在data中定義一個空listHeight數(shù)組;數(shù)組中的元素代表了每個li到this.foodScroll最頂部的區(qū)域高度;
_calculateHeight(){ //這個方法為了獲取每個商品類的最大區(qū)間的高度
let height = 0; let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook'); this.listHeight.push(height); //listHeight這個數(shù)組是用來存放右側(cè)商品中每個類型商品的最大區(qū)間高度的集合 for(var i=0;i<foodLsit.length;i++){ let item = foodLsit[i]; //clientHeight代表元素的高度 height += item.clientHeight; //每個元素的高度等于自身高度加上上一個元素的高度 this.listHeight.push(height); //最終listHeight集合了所有l(wèi)i[類為food-list-hook]到最頂部的高度 } }, let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');
foodLsit表示所有l(wèi)i【 <li class="food-list food-list-hook">】dom集合;
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Ant Design moment對象和字符串之間的相互轉(zhuǎn)化教程
這篇文章主要介紹了Ant Design moment對象和字符串之間的相互轉(zhuǎn)化教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10巧妙運用v-model實現(xiàn)父子組件傳值的方法示例
這篇文章主要介紹了巧妙運用v-model實現(xiàn)父子組件傳值的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04IDEA中Debug調(diào)試VUE前端項目調(diào)試JS只需兩步
這篇文章主要為大家介紹了在IDEA中Debug調(diào)試VUE前端項目,只需要兩步就可以調(diào)試JS的實現(xiàn)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-02-02Vue 2.5.2下axios + express 本地請求404的解決方法
下面小編就為大家分享一篇Vue 2.5.2下axios + express 本地請求404的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02vue插件--仿微信小程序showModel實現(xiàn)模態(tài)提示窗功能
這篇文章主要介紹了vue插件--仿微信小程序showModel實現(xiàn)模態(tài)提示窗,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08解決VUE自定義拖拽指令時 onmouseup 與 click事件沖突問題
這篇文章主要介紹了解決VUE自定義拖拽指令時 onmouseup 與 click事件沖突問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07Vue3學(xué)習(xí)之語法糖、箭頭函數(shù)、函數(shù)聲明詳解
在Vue3中箭頭函數(shù)被廣泛支持,尤其是在組合式API的上下文中,這篇文章主要給大家介紹了關(guān)于Vue3學(xué)習(xí)之語法糖、箭頭函數(shù)、函數(shù)聲明的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-08-08