better-scroll 是什么

better-scroll 是一款重点解决移动端(已支持 PC)各种滚动场景需求的插件。它的核心是借鉴的 iscroll 的实现,它的 API 设计基本兼容 iscroll,在 iscroll 的基础上又扩展了一些 feature 以及做了一些性能优化。

better-scroll 是基于原生 JS 实现的,不依赖任何框架。它编译后的代码大小是 63kb,压缩后是 35kb,gzip 后仅有 9kb,是一款非常轻量的 JS lib。


起步

学习使用 better-scroll 最好的方式是看它的 demo 代码,我们把代码都放在了 example 目录。由于目前最适合移动端开发的前端 mvvm 框架是 Vue,并且 better-scroll 可以很好的和 Vue 配合使用的,所以 demo 我都用 Vue 进行了重写。

better-scroll 最常见的应用场景是列表滚动,我们来看一下它的 html 结构

1
2
3
4
5
6
7
8
<div class="wrapper" ref="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- 这里可以放一些其它的 DOM,但不会影响滚动 -->
</div>

上面的代码中 better-scroll 是作用在外层 wrapper 容器上的,滚动的部分是 content 元素。这里要注意的是,better-scroll 只处理容器(wrapper)的第一个子元素(content)的滚动,其它的元素都会被忽略。

最简单的初始化代码如下:

1
2
3
4
import BScroll from 'better-scroll'
//let wrapper = document.querySelector('.wrapper') // 现在一般是使用ref 来获取wrapper 比较准确
let wrapper = this.$refs.wrapper
let scroll = new BScroll(wrapper)

better-scroll 提供了一个类,实例化的第一个参数是一个原生的 DOM 对象。当然,如果传递的是一个字符串,better-scroll 内部会尝试调用 querySelector 去获取这个 DOM 对象,所以初始化代码也可以是这样:

1
2
import BScroll from 'better-scroll'
let scroll = new BScroll('.wrapper')

滚动原理

很多人已经用过 better-scroll,我收到反馈最多的问题是:

better-scroll 初始化了, 但是没法滚动。

不能滚动是现象,我们得搞清楚这其中的根本原因。在这之前,我们先来看一下浏览器的滚动原理: 浏览器的滚动条大家都会遇到,当页面内容的高度超过视口高度的时候,会出现纵向滚动条;当页面内容的宽度超过视口宽度的时候,会出现横向滚动条。也就是当我们的视口展示不下内容的时候,会通过滚动条的方式让用户滚动屏幕看到剩余的内容。

better-scroll 也是一样的原理,我们可以用一张图更直观的感受一下:

绿色部分为 wrapper,也就是父容器,它会有固定的高度。黄色部分为 content,它是父容器的第一个子元素,它的高度会随着内容的大小而撑高。那么,当 content 的高度不超过父容器的高度,是不能滚动的,而它一旦超过了父容器的高度,我们就可以滚动内容区了,这就是 better-scroll 的滚动原理。


安装


NPM

better-scroll 托管在 Npm 上,执行如下命令安装:

1
npm install better-scroll --save

接下来就可以在代码中引入了,webpack 等构建工具都支持从 node_modules 里引入代码:

1
import BScroll from 'better-scroll'

如果是 ES5 的语法,如下:

1
var BScroll = require('better-scroll')

script 加载

better-scroll 也支持直接用 script 加载的方式,加载后会在 window 上挂载一个 BScroll 的对象。

你可以直接用:https://unpkg.com/better-scroll/dist/bscroll.min.js 这个地址。也可以把 dist 目录下的文件拷贝出去发布到自己的 cdn 服务器。


better-scroll 在Vue项目中的使用


对better-scroll 的简单使用


1、由上面知道我们在使用better-scroll 的时候,必须将内容包括在一个wrapper 容器中,里面还有一个content容器,而且我们滚动的内容必须包括在一个标签中,比如上面的ul ,content中只有ul标签。

2、我们在better-scroll 初始化的时候,必须在 mounted() 函数中。因为在vue的生命周期中,到了mounted阶段才有真实的DOM,我们才可以获取到 wrapper 。

3、我们还要给wrapper设置一个固定的高度,用于显示滚动。


测试结果:


监听滚动位置


默认情况下 better-scroll 是无法实时监听页面的滚动位置的。 这样我们就需要给 better-scroll 进行一些配置。

1
2
3
4
5
mounted () {
this.bscorll = new bScorll(this.$refs.wrapper,{
//在这里添加配置项
})
},


probeType

  类型:Number

  默认值:0

  可选值:1、2、3

作用:有时候我们需要知道滚动的位置。

当 probeType 为 1 的时候,会非实时(屏幕滑动超过一定时间后)派发scroll 事件

当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件;(在手指滚动的过程中侦测,手指离开后的惯性滚动过程中不侦测。)

当 probeType 为 3 的时候,不仅在屏幕滑动的过程中,而且在 momentum 滚动动画运行过程中实时派发 scroll 事件。( 就是我们用手用力滑动的时候,手放开之后,屏幕还在滑动,这就叫momentum 滚动动画 )

如果没有设置该值,其默认值为 0,即不派发 scroll 事件。


上拉加载更多


传送门

当我们上拉页面的时候 有时候需要请求更多的数据,这个时候就可以使用上拉加载pullup 。

效果图:


等我们将新的数据展示完成之后,如果我们还有继续去上拉加载请求数据的话,就不行了。

我们可以这样做:

在请求完成数据之后,用bscorll 实例去调用 finnishPullUp() 函数。这样在可以多次使用上拉加载了。

click 事件

BetterScroll 默认会阻止浏览器的原生 click 事件。当设置为 true,BetterScroll 会派发一个 click 事件,我们会给派发的 event 参数加一个私有属性 _constructed,值为 true。

比如我们给 第一个里添加一个点击事件liclick。

我们发现设置点击事件之后 点击并没有什么反应。


当我配置了 click:true 之后。我们在点击,就会有效果。


对better-scroll 进行封装


我们为什么要对better-scroll 进行封装呐?我们来看一个图


如果我们不封装,直接在每一个页面中都引入better-scroll ,耦合度太强,由于better-scroll是第三方插件,如果哪一天这个插件不能使用,不再出现重大bug,不再维护了,我们就需要每个页面都需要修改,很是不好。

当我们封装一下的时候,我们使用滚动的时候,只需要面向 我们封装的scroll.vue 来使用,而scroll.vue 是面向 better-scroll 的。这样即使有一天这个插件不能使用,不再出现重大bug,不再维护了。我们只需修改我们封装的scroll.vue 即可。


我这里对scroll.vue 进行简单的封装一下 。scroll.vue

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
<template>
<div ref="wrapper">
<div class="content">
<slot></slot>
</div>
</div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
data () {
return {
scroll: null
}
},
// 组件创建完后调用。
mounted () {
this.scroll = new BScroll(this.$refs.wrapper,{
click:true

})
}

}
</script>

<style scoped>

</style>

如果有需要其他的功能,我们可以自己添加。

使用:

引入scroll.vue,并注册,将滚动的内容 添加到 注册的标签中。并为其设置一个高度


官方文档

BetterScroll 2.X 里面,我们将 1.X 耦合的 feature 拆分至插件,以达到按需加载、减少包体积的目的。因此,@better-scroll/core 只提供了最核心的滚动能力。如果想要实现上拉刷新下拉加载的功能,你需要使用对应的插件

BetterScroll 1.x : 传送门

BetterScroll 2.x :传送门

当 better-scroll 遇见 Vue:传送门