一.實現思路
(1)實現上是左右分別一個better-scroll列表
(2)利用計算右側列表每一個大區塊的高度來計算左側的位置
- 1
- 2
二.實現
1.實現左右兩個better-scroll
(1)dom結構(better-scroll要求,會把最外層dom的第一個子元素作爲要滾動的區域)
左邊滾動列表dom
<div class="menu-wrapper" v-el:menu-wrapper>
<ul>
<li v-for="item in goods" class="menu-item"
:class="{'current':currentIndex === $index}"
@click="selectMenu($index,$event)">
<span class="text border-1px">
<span v-show="item.type > 0" class="icon"
:class="classMap[item.type]"></span>{{item.name}}
</span>
</li>
</ul>
</div>
右邊滾動列表dom
<div class="food-wrapper" v-el:food-wrapper>
<ul>
<li v-for="item in goods" class="food-list food-list-hook">
<h1 class="title">{{item.name}}</h1>
<ul>
<li v-for="food in item.foods" class="food-item border-1px">
<div class="icon">
<img width="57" height="57" :src="food.icon">
</div>
<div class="content">
<h2 class="name">{{food.name}}</h2>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span class="count">月售{{food.sellCount}}份</span>
<span>好評率{{food.rating}}%</span>
<div class="price">
<span class="now">¥{{food.price}}</span>
<span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>
</div>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
在數據請求完成後的$nextTick中初始化better-scroll,就能實現兩個列表分別能滾動,至於聯動,要後面自己做
_initScroll() {
this.menuScroll = new BScroll(this.$els.menuWrapper,{
click:true //允許better-scroll列表上的點擊事件
});
this.foodsScroll = new BScroll(this.$els.foodWrapper,{
probeType : 3 //讓better-scroll監聽scroll事件
});
this.foodsScroll.on('scroll',(pos) => {
this.scrollY =Math.abs(Math.round(pos.y));
})
},
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
2.實現聯動效果
(1)具體的聯動實現思路
- 在渲染完成後($nextTick內),初始化better-scroll,並在初始化函數內添加右側列表的scroll監聽事件,並記錄scrollY值到,存入vue的data中
- 在渲染完成後($nextTick內),計算右側列表的每一個大區塊的高度,並累加,存入數組listHeight
- 因爲scrollY值在滾動中總是不斷變化的,所以在computed中計算出currentIndex,當前滾動區域是哪一個大區塊,也就是listHeight數組的下標
- 在dom中根據currentIndex應用左側列表被點中的樣式
- 在左側列表某一項被點中的時候,右側列表滑動到某一個大塊區域,
//初始化better-scroll
_initScroll() {
this.menuScroll = new BScroll(this.$els.menuWrapper,{
click:true
});
this.foodsScroll = new BScroll(this.$els.foodWrapper,{
probeType : 3
});
this.foodsScroll.on('scroll',(pos) => {
this.scrollY =Math.abs(Math.round(pos.y));
})
},
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
_calculateHeight() {
let foodList = this.$els.foodWrapper.getElementsByClassName("food-list-hook");
let height = 0;
this.listHeight.push(height);
for(let i=0;i<foodList.length;i++) {
let item = foodList[i];
height += item.clientHeight;
this.listHeight.push(height);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
computed: {
currentIndex() {
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)){
return i;
}
}
return 0;
}
},
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
<div class="menu-wrapper" v-el:menu-wrapper>
<ul>
<!-- :class="{'current':currentIndex === $index}" 就是根據currentIndex應用左側列表被點中的樣式 -->
<li v-for="item in goods" class="menu-item"
:class="{'current':currentIndex === $index}"
@click="selectMenu($index,$event)">
<span class="text border-1px">
<span v-show="item.type > 0" class="icon"
:class="classMap[item.type]"></span>{{item.name}}
</span>
</li>
</ul>
</div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
//被點擊事件
//dom
<div class="menu-wrapper" v-el:menu-wrapper>
<ul>
<!-- @click="selectMenu($index,$event)" 就是點擊事件 -->
<li v-for="item in goods" class="menu-item"
:class="{'current':currentIndex === $index}"
@click="selectMenu($index,$event)">
<span class="text border-1px">
<span v-show="item.type > 0" class="icon"
:class="classMap[item.type]"></span>{{item.name}}
</span>
</li>
</ul>
</div>
//js
selectMenu(index,event) {
if(!event._constructed) {
return ;
}
let foodList = this.$els.foodWrapper.getElementsByClassName("food-list-hook");
let el = foodList[index];
this.foodsScroll.scrollToElement(el,300);
},