better-scroll的原理
1.什么是 better-scroll?
better-scroll 是一个移动端滚动的解决方案,它不仅可以做普通的滚动列表,还可以做轮播图、picker 等等。
2.better-scroll的滚动原理?
先来看一下浏览器的滚动原理,浏览器的滚动条大家都会遇到,当页面内容的高度超过视口高度的时候,会出现纵向滚动条;当页面内容的宽度超过视口宽度的时候,会出现横向滚动条。也就是当我们的视口展示不下内容的时候,会通过滚动条的方式让用户滚动屏幕看到剩余的内容。那么对于 better-scroll 也是一样的道理,我们先来看一下 better-scroll 常见的 html 结构:
为了更加直观,我们再来看一张图:
绿色部分为 wrapper,也就是父容器,它会有固定的高度。黄色部分为 content,它是父容器的第一个子元素,它的高度会随着内容的大小而撑高。那么,当 content 的高度不超过父容器的高度,是不能滚动的,而它一旦超过了父容器的高度,我们就可以滚动内容区了,这就是 better-scroll 的滚动原理。
那么,我们怎么初始化 better-scroll 呢,如果是上述 html 结构,那么初始化代码如下:
import BScroll from 'better-scroll' let wrapper = document.querySelector('.wrapper') let scroll = new BScroll(wrapper, {})
better-scroll 对外暴露了一个 BScroll 的类,我们初始化只需要 new 一个类的实例即可。第一个参数就是我们 wrapper 的 DOM 对象,第二个是一些配置参数,具体参考 better-scroll 的文档。
better-scroll 的初始化时机很重要,因为它在初始化的时候,会计算父元素和子元素的高度和宽度,来决定是否可以纵向和横向滚动。因此,我们在初始化它的时候,必须确保父元素和子元素的内容已经正确渲染了。如果子元素或者父元素 DOM 结构发生改变的时候,必须重新调用 scroll.refresh()
方法重新计算来确保滚动效果的正常。所以同学们反馈的 better-scroll 不能滚动的原因多半是初始化 better-scroll 的时机不对,或者是当 DOM 结构发送变化的时候并没有重新计算 better-scroll。
如何在 Vue 中使用 better-scroll
Vue.js 提供了我们一个获取 DOM 对象的接口—— vm.$refs
。在这里,我们通过了 this.$refs.wrapper
访问到了这个 DOM 对象,并且我们在 mounted 这个钩子函数里,this.$nextTick
的回调函数中初始化 better-scroll 。因为这个时候,wrapper 的 DOM 已经渲染了,我们可以正确计算它以及它内层 content 的高度,以确保滚动正常。
异步数据的处理
在我们的实际工作中,列表的数据往往都是异步获取的,因此我们初始化 better-scroll 的时机需要在数据获取后,代码如下:
---------------------------------------------------------------------------------------------------
之前在做去哪儿网项目中better-scroll失效的原因过程如下:
可以很清晰的看到,上述代码中并没有父级盒子,于是我加了个父级盒子,也给父级盒子给了一个固定的高度,然后就能正常滚动起来了,具体的实现过程如下: