組件全部代碼
<template>
<div class="goods">
<!--左側區域-->
<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>
<!--右側區域-->
<div class="foods-wrapper" ref="right">
<ul>
<li class="food-list food-list-hook"
v-for="(item,index) in dataLlist.goods"
:key="index">
<!--標題區域-->
<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 ,//爲了實現左右區域映射
}
},
computed:{
currentIndex(){ //這個返回的是下標,當這個currentIndex的值與goods的下標一致的時候,
// 左側區域就會呈現高亮現象
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) //實現當滑動的時候,左側隱藏的食物類型顯示
return i;
}
}
return 0;
}
},
created(){
//dataLlist數據是異步加載,直接用new BScroll時,dom可能還沒有更新
this.$nextTick(()=>{ //this.$nextTick()將回調延遲到下次 DOM 更新循環之後執行,使用$nextTick異步初始化Bscroll
this.meunScroll=new BScroll(this.$refs.left,{
click:true
});
this.foodScroll=new BScroll(this.$refs.right,{
probeType: 3 //可以派發scroll事件,檢測到實時滾動的位置
});
this.foodScroll.on('scroll',(pos) =>{
//參數pos就是在右側區域滑動的實時位置
//Math.round()取整數,Math.abs取絕對值
this.scrollY =Math.abs( Math.round(pos.y));
});
this._calculateHeight(); //這個方法爲了獲取每個商品類的最大區間的高度
})
},
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(){ //這個方法爲了獲取每個商品類的最大區間的高度
let height = 0;
let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');
this.listHeight.push(height); //listHeight這個數組是用來存放右側商品中每個類型商品的最大區間高度的集合
for(var i=0;i<foodLsit.length;i++){
let item = foodLsit[i];
//clientHeight代表元素的高度
height += item.clientHeight; //每個元素的高度等於自身高度加上上一個元素的高度
this.listHeight.push(height); //最終listHeight集合了所有li[類爲food-list-hook]到最頂部的高度
}
},
selectIndex(index,ele){
//better-scroll 會禁止移動端的點擊事件,需要重新派發,同時在PC端會點擊兩次,此處需要做判斷
if(!ele._constructed){
//better-scroll的派發事件scroll的event和pc端瀏覽器的點擊事件的event有個
// 屬性區別_constructed,pc端瀏覽器的點擊事件的event中是沒有這個屬性的
return;
}
let rightItem =this.$refs.right.getElementsByClassName('food-list-hook');
let item = rightItem[index]; //找到相應的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實現菜單滑動功能
- 安裝和在組件中引入better-scroll
npm install better-scroll --save
引入import BScroll from 'better-scroll' 【在組件中引入,在後續的export default中就可以直接使用封裝好的better-scroll功能了】
- better-scroll實現的下面功能
在菜單中要實現點擊左側菜單的食品類型名稱,右側就會自動滑動到此食品類型下的所有食品;在右側區域中滑動到食品類型下的所有食品區域下的時候,左側菜單會出現相應的高亮效果
如何實現上面的功能:
第一:需要知道要在哪些區域間實現滑動
第二:通過new BScroll()獲取要實現滑動的區域
this.meunScroll=new BScroll(this.$refs.left);
this.foodScroll=new BScroll(this.$refs.right);
第三:上面代碼在理論上應該在相應的區域都應該能滑動了,但是現實是並不能滑動
原因是:數據的獲取是異步獲取的,在定義滑動區域的時候,也許數據還沒有更新,這是this.meunScroll的高度可能就沒有高度外部類goods的高度,這樣就不會滑動。
解決的方法:this.$nextTick()將回調延遲到下次 DOM 更新循環之後執行,使用$nextTick異步初始化Bscroll
this.$nextTick(()=>{ //this.$nextTick()將回調延遲到下次 DOM 更新循環之後執行,使用$nextTick異步初始化Bscroll
this.meunScroll=new BScroll(this.$refs.left,{
click:true
});
this.foodScroll=new BScroll(this.$refs.right,{
probeType: 3 //可以派發scroll事件,檢測到實時滾動的位置
});
this.foodScroll.on('scroll',(pos) =>{
//參數pos就是在右側區域滑動的實時位置
//Math.round()取整數,Math.abs取絕對值
this.scrollY =Math.abs( Math.round(pos.y));
});
this._calculateHeight(); //這個方法爲了獲取每個商品類的最大區間的高度
})