这篇主要写下关于better-scroll的用法, 来实现菜单和商品的左右联动。
在good组件中,用flex布局左边的菜单和右边的商品两部分。通过v-for将数据渲染进去。
左侧为menu-wrapper部分,右侧为food-wrapper部分。
- 下载,引入better-scroll插件
import BScroll from 'better-scroll'
- 配置BScroll在钩子函数created中,获取数据之后,使用$nextTick异步初始化Bscroll
<div class="food-wrapper" ref="foodScroll">
data(){
return {
sorollY:0
}
}
created() {
axios.get('data/good.json').then(res => {
this.menu = res.data.data.menu
this.food = res.data.data.food
this.$nextTick(() => {
this.scroll = new BScroll(this.$refs.foodScroll,{
probeType: 3 //可以派发scroll事件
});
this.scroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y))
console.log(this.scrollY)
})
this.calcFoodHeight();
})
}).catch(err => console.log(err))
probeType为3表示better-scroll可以监听scroll事件,click:true表示可以拥有点击事件。
scroll事件返回的回调函数pos.y就是Y轴的滚动值,往下滑是负值,往上滑是正值,所以四舍五入取绝对值储存在scrollY中。
详细的可以去看下文档https://ustbhuangyi.github.io/better-scroll/doc/api.html
- 将food-wrapper的每项商品li的高度累加,push到一个新数组listHeight中,数组的第一项为0;在我这个demo中,每项商品都是3个,比如饮料这部分的高度为200.那么这个数组就是[0,200,400,600...]
在computed中,遍历这个数组。如果滚动值scrollY大于等于i区间,小于i+1区间,那么说明此时滚动到i区间中,比如:滚动到西瓜这里,listHeight[2]>scrollY>listHeight[1] 说明此时在i=1的区间里。也就是水果的区间里。大于等于listHeight[i]是为了避免既不在i区间也不在i+1区间这种情况。因为我们的scrollY是四舍五入的值,也可能会有1像素左右的差距的。
<li class="food-item food-list-hook" v-for="(item,index) in food">
data() {
return {
menu:[],
food:[],
listHeight:[],
scrollY: 0
}
},
methods: {
calcFoodHeight() {
let foodlist = this.$refs.foodScroll.getElementsByClassName('food-list-hook');
// console.log(foodlist)
let height = 0;
this.listHeight.push(height);
for(let i = 0; i < foodlist.length; i++) {
height += foodlist[i].clientHeight;
this.listHeight.push(height)
}
console.log(this.listHeight)
},
computed: {
currentIndex() {
for (let i = 0; i < this.listHeight.length; i++) {
let height1 = this.listHeight[i];
let height2 = this.listHeight[i+1]
if((this.scrollY >= height1 && this.scrollY < height2)){
return i
}
}
}
}
因为currentIndex返回的是下标。所以在menu-item中绑定一个class属性,当且仅当这个li的下标index和currentIndex返回的下标相同时,才渲染current这个样式。实现了左右联动的效果。
<li ref="menuItem" class="menu-item" :class="{'current': currentIndex === index }" v-for="(item, index) in menu">{{item.name}}</li>
- 如果实现点击滚动呢,简单,绑定个click方法。点击传入此时的index,然后在方法中通过传入的下标滚动到相应的li
selectIndex(index) {
let foodlist = this.$refs.foodScroll.getElementsByClassName('food-list-hook');
this.scroll.scrollToElement(foodlist[index], 250) //better-scroll的scrollToElement方法滚动到指定位置
}
scrollToElement(el, time, offsetX, offsetY, easing)第一个值接收目标元素,第二个是滚动时间,第三第四个是相对于目标元素的偏移量。