最近在学习一个Vue-H5的仿外卖的移动端项目。其中,很多滚动场景,包括滚动列表、轮播图等是用Better-Scroll插件实现的。具体使用方法参考better-scroll中文文档。使用过程中遇到问题:横向滑动不起作用,下面针对这个问题进行阐述。
better-scroll 滚动原理
在分析问题之前,我们有必要先介绍一下better-scroll的滚动原理,这里借用原作者的图,如下。
如图示,绿色部分为wrapper,也就是父容器,他的高度时固定的。黄色部分是content,这个是父容器的第一个子元素,它的高度会随着里面的内容大小而撑高。因此,只有当content的高度大于wrapper的高度时,我们才可以滚动内容区。
横向滑动问题
项目源码
<template>
<div class="shop-info">
<div class="info-content">
<section class="section">
<h3 class="section-title">商家实景</h3>
<div class="pic-wrapper">
<ul ref="picsUl" class="pic-list" >
<li
v-for="(pic, index) in info.pics"
:key="index"
class="pic-item">
<img v-lazy="pic" width="120" height="90">
</li>
</ul>
</div>
</section>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['info'])
},
watch: {
info() { // 刷新流程--> 更新数据
this.$nextTick(() => {
this._initScroll()
})
}
},
mounted() {
// 如果this.info.pics数据还没有, 直接结束
if (!this.info.pics) {
return
}
// this.info.pics有数据了, 可以创建BScroll对象形成滑动
this._initScroll()
},
methods: {
_initScroll() {
new BScroll('.pic-wrapper', {
scrollX: true // 水平滑动
})
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import "../../../common/stylus/mixins.styl"
.shop-info
position absolute
top 195px
bottom 0
left 0
width 100%
background #fff
overflow hidden
.section
padding 16px 14px 14px
font-size 16px
background-color #fff
color #666
border-bottom 1px solid #eee
position relative
.section-title
color #000
font-weight 700
line-height 16px
> .iconfont
float right
color #ccc
.pic-wrapper
width: 100%
overflow: hidden
white-space: nowrap
margin-top 16px
.pic-list
font-size: 0
.pic-item
display: inline-block
margin-right: 6px
width: 120px
height: 90px
&:last-child
margin: 0
</style>
问题分析
分析Element元素可以看出,元素ul的宽度并没有被里面的几个li元素的宽度撑开。所以在初始化 better-scroll时,ul的宽度并没有大于ul的父元素pic-wrapper的宽度,因此better-scroll并不生效。
解决方法
从上面的分析可以得出,我们只要在初始化 better-scroll之前,将元素ul的宽度设置为元素li再加上其margin的值即可。
methods: {
_initScroll() {
// 动态计算ul的宽度
const ul = this.$refs.picsUl
const liWidth = 120 // li width : 120px
const space = 6 // margin-right: 6px
const count = this.info.pics.length
ul.style.width = (liWidth + space) * count - space + 'px'
new BScroll('.pic-wrapper', {
scrollX: true // 水平滑动
})
}
}
这样就解决了横向滑动的问题,我们再看一下Element相应的元素。ul的宽度有了,并且大于其父元素的宽度,当我们横向滑动时,ul样式中的transform也在变化。
总结
使用better-scroll时,我们要先弄明白其滚动的原理,然后需要分析使用的时机。一般我们是在页面加载之后或者数据更新之后再去初始化 better-scroll。在Vue中,数据是异步更新的,可以在this.$nextTick回调中初始化 better-scroll 。
还需要注意的是,有时候,我们需要在new BScroll()之前,手动的设置content的宽度或者高度。