参考:https://juejin.cn/post/6844903655108280328
效果
BetterScroll
//安装
npm install better-scroll --save
//导入
import Bscroll from "better-scroll";
滚动原理:需要一个固定高度的父容器,然后在其基础上进行滚动。
//设scrollH为父容器高度,例:
this.scrollH= window.innerHeight - 150
整体结构
相关数据
data() {
return {
foodList:[],//菜品信息
scrollH:'',//滚轮窗口的高度
heightList:[],//储存位置
scrollY:'',//滚动距离
};
},
例-foodList数据结构:
foodList:[
{name:'菜类',foods:['娃娃菜','大白菜']},
{name:'肉类',foods:['猪肉','牛肉']},
{name:'水果',foods:['苹果','西瓜']},
{name:'甜品',foods:['奶茶','华夫饼']},
],
相关DOM
左侧菜单栏
<div ref="leftMenu">
<ul>
<li
v-for="(item, index) in foodList"
:key="index"
:class="{ active: currentIndex === index }"
@click="selectLeft(index)"
>
{{ item.name }}
</li>
</ul>
</div>
ref="leftMenu"
获取左侧菜单栏的dom,用于创建滚动窗口@click="selectLeft(index)"
点击左侧菜单后触发,用于滑动到指定内容:class="{ active: currentIndex === index }"
动态改变样式
右侧内容栏
<div ref="rigntMenu" :style="'height:' + scrollH + 'px'" style="overflow: hidden">
<ul>
<li v-for="(item, index) in foodList"
:key="index"
ref="rightItem">
<span class="rightTitle">{{ item.name }}</span>
<div
v-for="(food, key) in item.foods"
:key="key"
>
{{ food }}
</div>
</li>
</ul>
</div>
ref="rigntMenu"
获取右侧内容栏的dom,用于创建滚动窗口ref="rightItem"
获取某一品类的dom高度:style="'height:' + scrollH + 'px'"
动态绑定固定容器的高度
函数与方法
创建滚动窗口
通过new Bscroll(对应dom,{相关配置})
创建滚动窗口
scrollInit() {
//创建左边菜单栏滚动窗口
this.leftMenu = new Bscroll(this.$refs.leftMenu, {
click: true,//允许点击
});
//创建右边内容栏滚动窗口
this.rigntMenu = new Bscroll(this.$refs.rigntMenu, {
probeType: 3, //在 rigntMenu 滚动时触发 scroll 事件
click: true,
});
//当右侧滚动时,监听滚动事件获取滚动距离,将滚动距离储存在scrollY中
//滚动距离:容器顶部与内容顶部的距离
this.rigntMenu.on("scroll", (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
});
},
获取右侧项目位置
getListHeight(){
const lis=this.$refs.rightItem //获取每项的DOM
this.heightList=[] //储存每项的顶部位置
let height=0
this.heightList.push(height) //第一项的顶部垂直位置为0
lis.map(item=>{
height+=item.clientHeight //第二项顶部位置=第一项顶部位置+第二项的内容高度,以此类推
this.heightList.push(height)
})
},
右侧联动左侧
computed: {
currentIndex() {
//根据当前滚轮滑动的距离 判断左侧菜单现处位置
const index = this.heightList.findIndex((item, index) => {
return (this.scrollY >= this.heightList[index] &&
this.scrollY < this.heightList[index + 1])
});
return index > 0 ? index : 0;
},
},
左侧联动右侧
selectLeft(index) {
let rightItem = this.$refs.rightItem;
let el = rightItem[index]; //根据索引获取对应dom
this.rigntMenu.scrollToElement(el, 1000); //将右侧滚动窗口滚动至对应dom
},
初始化
mounted() {
this.scrollH= window.innerHeight - 150
this.$nextTick(() => {
this.scrollInit()
this.getListHeight()
})
}
如果是动态数据,下面的内容可以写在获取数据的函数内部的结尾。
this.$nextTick(() => {
this.scrollInit()
this.getListHeight()
})