说明
- 最近想做一个vue商城小项目,练习一下vue的语法,刚刚好碰到了需要左右菜单实现联动,因此就接触了 better-scroll。
代码
//页面结构
<template>
<div id="wrap">
<div class="goodMenu" ref="goodMenu">
<ul>
<li v-for="(item ,index) in goodMenu" :key="index"
:class="{active: currentIndex === index}"
@click="selectLeft(index)" ref="lItem">{{ item}}</li>
</ul>
</div>
<div class="goodList" ref="goodList">
<ul>
<li v-for="(items, index) in goodList" :key="index" ref="rItem">
<p>{{ items.name}}</p>
<div v-for="(item, key) in items.data" :key="key">
{{ item}}
</div>
</li>
</ul>
</div>
</div>
</template>
//数据
<script>
export default {
data(){
return {
goodMenu: ['菜单1', '菜单2','菜单3', '菜单4', '菜单5', '菜单6', '菜单7', '菜单8'],
goodList: [
{ name: '菜单1', data: ['1.1', '1.2', '1.3', '1.4', '1.5']},
{ name: '菜单2', data: ['1.1', '1.2', '1.3', '1.4', '1.5', '1.6']},
{ name: '菜单3', data: ['1.1', '1.2', '1.3', '1.4', '1.5']},
{ name: '菜单4', data: ['1.1', '1.2', '1.3', '1.4', '1.5']},
{ name: '菜单5', data: ['1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8']},
{ name: '菜单6', data: ['1.1', '1.2', '1.3', '1.4', '1.5']},
{ name: '菜单7', data: ['1.1', '1.2', '1.3', '1.4']},
{ name: '菜单8', data: ['1.1', '1.2']},
],
scrollY: 0,//获取实时滚动位置
heightList: []//获取每一个li的高度
}
}
</script>
- 渲染结果
- 左边菜单栏(goodMenu)。
- 右边菜单栏(goodList),每一项有一个标题:name,以及菜单数据: data数组。再结合 v-for指令及相关样式即可完成页面简单布局(不是重点)
- 其他数据先不必理会,先把页面结构渲染出来,下面会一一讲解。
- 元素纵轴滚动
- 元素可以滚动,父元素高度固定,overflow为 hidden,子元素高度超过父元素高度即可滑动,不多解释。
- 左菜单、右菜单可以在父元素滑动
- 左菜单栏因为要用到 click事件,默认better-scroll是默认阻止 click事件,设置为true派发一个click事件。
- 右菜单栏,因为需要滚动,并且需要获取实时滚动距离scrollY,因此设置 probeType设置为3,它有三个值1、2、3。看以查看文档probeType。
//引入better-scroll
import Bscroll from 'better-scroll'
export default {
created(){
//因为 _scrollInit函数需要操作DOM,因此必须在DOM元素存在文档中才能获取DOM节点
//因此在 nextTick回调函数里面调用可以是实现此功能
this.$nextTick(() => {
this._scrollInit()
this.getHeight()
})
},
methods:{
//初始化 better-scroll
_scrollInit(){
this.menuList = new Bscroll(this.$refs.goodMenu, {
click: true
})
this.goodmenu = new Bscroll(this.$refs.goodList, {
probeType: 3
})
this.goodmenu.on('scroll', (pos) =>{
//获取实时滚动的距离 使用scrollY接收
this.scrollY = Math.abs(Math.round(pos.y))
})
}
}
- 获取右菜单栏每个li的高度
- 这里获取 li 的高度即为当前li的高度加上之前 li 的高度,第一个元素为 0(必须)
methods: {
getHeight(){
//获取每一个li的高度
const lis = this.$refs.rItem
//heightList的第一个元素为0
let height = 0
this.heightList.push(height)
//之后的高度即为当前li的高度加上之前面li的高度和
lis.forEach(item =>{
height += item.clientHeight
this.heightList.push(height)
})
}
}
- 右菜单滚动,左菜单同步
- 这里就是根据右菜单滑动的距离以及每一个每一个 li 的高度的比较返回当前应该显示左菜单 li的索引,让该 li 高亮显示,即:class="{active: currentIndex === index}"。
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 rItem = this.$refs.rItem
let el = rItem[index]
this.goodmenu.scrollToElement(el, 1000)
}
- 问题:有时候 currentIndex 会判断不准确,是滑动距离scrollY 以及右菜单 li的高度比较问题,同样一段代码,每个项目遇到的问题都是不一样的,我也是参考网上很多的例子,发现一到自己这里就出现了很多问题,每个人遇到的问题都是不一样的,结合自己的问题,想办法解决,这也是成长的一部分。