說明
- 最近想做一個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的高度比較問題,同樣一段代碼,每個項目遇到的問題都是不一樣的,我也是參考網上很多的例子,發現一到自己這里就出現了很多問題,每個人遇到的問題都是不一樣的,結合自己的問題,想辦法解決,這也是成長的一部分。