如果你是用vue写移动端的话,我推荐使用better-scroll。
better-scroll的使用可以参考better-server文档:https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/
Template
<template>
<div class="goods">
<div class="menu-wrapper" ref="menuWrapper">
<ul>
<li v-for="(item,index) in goods" :key="item.id" 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>
<span>{{item.name}}</span>
</span>
</li>
</ul>
</div>
<div class="foods-wrapper" ref="foodsWrapper">
<ul>
<li v-for="item in goods" class="food-list food-list-hook" :key="item.id">
<h1 class="title">{{item.name}}</h1>
<ul>
<li v-for="food in item.foods" class="food-item border-1px" :key="food.id">
<div class="icon">
<img :src="food.icon" width="57" height="57" alt="">
</div>
<div class="content">
<h2 class="name">{{food.name}}</h2>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span style="margin-right: 12px;">月售{{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>
<shopcart></shopcart>
</div>
</template>
JS
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
import shopcart from '../../components/shopcart/shopcart'
export default {
name: 'goods',
data () {
return {
goods: [],
listHeight: [],
scrollY: 0
}
},
props: {
seller: {
type: Object
}
},
created () {
this.$http.get('http://localhost:3003/goods').then((response) => {
if (response.status === 200) {
this.goods = response.body
this.$nextTick(() => {
this._initScroll()
this._calculateHeight()
})
console.log(this.goods)
} else {
console.log(response.body)
}
})
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee']
},
computed: {
currentIndex () {
for (let i = 0; i < this.listHeight.length; i++) {
let height = this.listHeight[i]
let height2 = this.listHeight[i + 1]
if (!height2 || (this.scrollY >= height && this.scrollY < height2)) {
console.log(i)
if (i >= 8) {
this.meunScroll.scrollTo(0, -39 - ((i - 8) * 54))
} else if (i === 0) {
this.meunScroll.scrollTo(0, 0)
}
return i
}
}
return 0
}
},
methods: {
_initScroll () {
this.meunScroll = new BScroll(this.$refs.menuWrapper, {
// 取消点击不出发
click: true
})
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
// 探针作用,实时监测滚动位置
probeType: 3
})
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)
}
},
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)
}
},
components: {
shopcart
}
}
</script>
CSS(我在vue项目中用的Stylus)
<style lang="stylus" rel="stylesheet/stylus">
@import "../../common/stylus/mixin.styl"
.goods
display flex
position absolute
top 174px
bottom 46px
width 100%
overflow hidden
.menu-wrapper
flex 0 0 80px
width 80px
background #f3f5f7
.menu-item
display table
height 54px
width 56px
line-height 14px
padding 0 12px
&.current
background #fff
position relative
z-index 10
font-weight 700
margin-top -1px
.text
border-none()
.icon
display: inline-block
vertical-align top
width: 12px
height:12px
margin-right: 2px
background-size: 12px 12px
background-repeat: no-repeat
&.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')
.text
display table-cell
width 56px
vertical-align middle
font-size 12px
border-1px(rgba(7,17,27,0.1))
.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
font-size 14px
margin 2px 0 8px 0
height 14px
line-height 14px
color rgb(7,17,27)
.desc,.extra
font-size 10px
line-height 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>
mixin.styl
border-1px($color)
position relative
&:after
display block
position absolute
left 0
bottom 0
width 100%
border-top: 1px solid $color
content: ' '
border-none()
&:after
display none
bg-image($url)
background-image: url($url+"@2x.png")
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
background-image: url($url + "@3x.png")