具体问题描述:
手机端当右边商品滚动到对应最后一个菜单“特色粥品”(超出屏幕长度隐藏的菜单),左边对应菜单栏仍隐藏不可见。如下图:
解决办法:
仿照点击菜单项右边商品栏滚动到对应位置的方法:
(1)在li的class添加menu-list-hook,该class没有具体的样式,用于在JS中获取对象。
(2)在计算高亮菜单项处添加scrollToElement,使左边菜单栏随之滚动到对应的菜单项。
更改后解决该问题。
商品页面goods.vue代码:
<template>
<div class="goods">
<div class="menu-wrapper" ref="menuWrapper">
<ul>
<li v-for="(item,index) in goods" :key="index" class="menu-item menu-list-hook" @click="selectMenu(index, $event)" :class="{'current':currentIndex===index}">
<span class="text border-1px">
<span v-show="item.type>0" class="icon" :class="classMap[item.type]"></span>{{item.name}}
</span>
</li>
</ul>
</div>
<div class="foods-wrapper" ref="foodsWrapper">
<ul>
<li v-for="(item, index) in goods" class="food-list food-list-hook" :key="index">
<h1 class="title">{{item.name}}</h1>
<ul>
<li v-for="(food,index) in item.foods" :key="index" class="food-item border-1px">
<div class="icon">
<img :src="food.icon" width="57px" height="57px">
</div>
<div class="content">
<h2 class="name">{{food.name}}</h2>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span>月售{{food.sellCount}}份</span>
<span>好评率{{food.rating}}%</span>
</div>
<div class="price">
<span class="now">¥{{food.price}}</span><span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll';
const ERR_OK = 0;
export default{
props: {
seller: {
type: Object
}
},
data() {
return {
goods: [],
listHeight: [],
scrollY: 0
};
},
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)) {
// 左边菜单栏随之滚动到对应菜单项
let menuList = this.$refs.menuWrapper.getElementsByClassName('menu-list-hook');
let menuel = menuList[i];
this.menuScroll.scrollToElement(menuel, 300);
return i;
}
}
return 0;
}
},
created() {
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
this.$http.get('/api/goods').then((response) => {
response = response.body;
if (response.errno === ERR_OK) {
this.goods = response.data;
// console.log(this.goods);
this.$nextTick(() => { // this.$nextTick( () => {} ):是一个异步函数,为了确保 DOM已经渲染完成
this._initScroll();
// 调用计算高度的方法
this._calculateHeight();
});
}
});
},
methods: {
selectMenu(index, event) {
if (!event._constructed) {
return;
}
let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
let el = foodList[index];
this.foodsScroll.scrollToElement(el, 300);
console.log(index);
},
_initScroll() {
this.menuScroll = new BScroll(this.$refs.menuWrapper, {
click: true
});
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
probeType: 3 // 设置scroll滚动时可以给出实时位置
});
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y)); // 获取实时滚动位置
});
},
_calculateHeight() {
let foodList = this.$refs.foodsWrapper.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);
}
}
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import "../../common/stylus/mixin"
.goods
display: flex
position: absolute
width: 100%
bottom: 46px // 购物车的高度
top: 174px // header+商品标签的高度
overflow: hidden
.menu-wrapper
flex: 0 0 80px //等分、内容不足缩放情况、占位空间
width: 80px
background: #f3f5f7
.menu-item
display: table //table保证一行或者两行字都保持垂直居中
height: 54px
width: 56px
line-height: 14px
padding: 0 12px
&.current
position: relative
z-index: 10
margin-top: -1px
background: #fff
font-weight: 700
.text
border-none()
.icon
display: inline-block
vertical-align: top
width: 12px
height: 12px
margin-right: 2px
&.decrease
bg-image('decrease_3')
&.discount
bg-image('discount_3')
&.guarantee
bg-image('guarantee_3')
&.invoice
bg-image('invoice_3')
&.special
bg-image('special_3')
background-size: 12px 12px
background-repeat: no-repeat
.text
display: table-cell
width: 56px
vertical-align: middle //垂直居中
border-1px(rgba(7,17,27,0.1))
font-size: 12px
.foods-wrapper
flex: 1
.title
padding-left: 14px
height: 26px
line-height: 26px
border-left: 2px solid #d9dde1
font-size: 12px
color: rgb(147, 153, 159)
background: #f3f5f7
.food-item
display: flex
margin: 18px
padding-bottom: 18px
border-1px(rgba(7,17,27,0.1))
&:last-child
border-none()
margin-bottom: 0
.icon
flex: 0 0 57px
margin-right: 10px
.content
flex: 1
.name
margin: 2px 0 8px 0
height: 14px
line-height: 14px
font-size: 14px
color: rgb(7, 17, 27)
.desc, .extra
line-height: 10px
font-size: 10px
color: rgb(147, 153, 159)
.desc
margin-bottom: 8px
line-height: 12px
.extra
.count
margin-right: 12px
.price
font-weight: 700
line-height: 24px
.now
margin-right: 8px
font-size: 14px
color: rgb(240, 20, 20)
.old
text-decoration: line-through
font-size: 10px
color: rgb(147, 153, 159)
</style>