Vue项目中使用better-scroll实现菜单映射功能方法

组件全部代码

<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中必须有 probeType: 3后才能进行下面的scroll事件】

this.foodScroll.on('scroll',(pos) =>{

//参数pos就是在右侧区域滑动的实时位置

//Math.round()取整数,Math.abs取绝对值

this.scrollY =Math.abs( Math.round(pos.y));

});

this._calculateHeight(); //这个方法为了获取每个商品类的最大区间的高度

})

获取每个右侧区域的 <li class="food-list food-list-hook">的高度

在data中定义一个空listHeight数组;数组中的元素代表了每个li到this.foodScroll最顶部的区域高度;

_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]到最顶部的高度

}

},

let foodLsit = this.$refs.right.getElementsByClassName('food-list-hook');

foodLsit表示所有li【 <li class="food-list food-list-hook">】dom集合;

以上是 Vue项目中使用better-scroll实现菜单映射功能方法 的全部内容, 来源链接: utcz.com/z/344263.html

回到顶部