使用
基础滚动
如果你只需要一个拥有基础滚动能力的列表,只需要引入 core。
import BScroll from '@better-scroll/core'
let bs = new BScroll('.wrapper', {
// ...... 详见配置项
})
增强型滚动
如果你需要一些额外的 feature。比如 pull-up
,你需要引入额外的插件,详情查看插件。
import BScroll from '@better-scroll/core'
import Pullup from '@better-scroll/pull-up'
// 注册插件
BScroll.use(Pullup)
let bs = new BScroll('.wrapper', {
probeType: 3,
pullUpLoad: true
})
全能力的滚动
如果你觉得一个个引入插件很费事,我们提供了一个拥有全部插件能力的 BetterScroll 包。它的使用方式与 1.0
版本一模一样,但是体积会相对大很多,推荐按需引入。
import BScroll from 'better-scroll'
let bs = new BScroll('.wrapper', {
// ...
pullUpLoad: true,
wheel: true,
scrollbar: true,
// and so on
})
配置项
BetterScroll 支持很多参数配置,可以在初始化的时候传入第二个参数,比如:
import BScroll from '@better-scroll/core'
let scroll = new BScroll('.wrapper',{
scrollY: true,
click: true
})
这样就实现了一个具有纵向可点击的滚动效果的列表。BetterScroll 支持的参数非常多,接下来我们来列举 BetterScroll 支持的参数。
startX
- 类型:
number
- 默认值:
0
- 作用:横轴方向初始化位置。
startY
- 类型:
number
- 默认值:
0
- 作用:纵轴方向初始化位置。
scrollX
- 类型:
boolean
- 默认值:
false
- 作用:当设置为 true 的时候,可以开启横向滚动。
- 备注:当设置 eventPassthrough 为 ‘horizontal’ 的时候,该配置无效。
scrollY
- 类型:
boolean
- 默认值:
true
- 作用:当设置为 true 的时候,可以开启纵向滚动。
- 备注:当设置 eventPassthrough 为 ‘vertical’ 的时候,该配置无效。
freeScroll
- 类型:
boolean
- 默认值:
false
- 作用:在默认情况下,由于人的手指无法做到绝对垂直或者水平的运动,因此在一次手指操作的过程中,都会存在横向以及纵向的偏移量,内部默认会摒弃偏移量较小的一个方向,保留另一个方向的滚动。但是在某些场景我们需要同时计算横向以及纵向的手指偏移距离,而不是只计算偏移量较大的一个方向,这个时候我们只要设置
freeScroll
为 true 即可。 - 备注:当设置 eventPassthrough 不为空的时候,该配置无效。
- 示例:
// 手指起点的坐标 e1: { pageX: 120, pageY: 120 }
// 手指终点的坐标 e2: { pageX: 121, pageY: 140 }
// offsetX: e2.pageX - e1.pageX = 1
// offsetY: e2.pageY - e1.pageY = 20
// 如果 freeScroll 为 false, 由于 offsetY > offsetX + directionLockThreshold
// offsetX 被重置为 0, 只保留 offsetY 的偏移量,因此只做一次纵向滚动
directionLockThreshold
- 类型:
number
- 默认值:
5
- 作用:当
freeScroll
为 false 的情况,我们需要锁定只滚动一个方向的时候,我们在初始滚动的时候根据横轴和纵轴滚动的绝对值做差,当差值大于directionLockThreshold
的时候来决定滚动锁定的方向。 - 备注:当设置 eventPassthrough 的时候,
directionLockThreshold
设置无效,始终为 0。
eventPassthrough
- 类型:
string
- 默认值:
''
- 可选值:
'vertical' | 'horizontal'
- 作用:有时候我们使用 BetterScroll 在某个方向模拟滚动的时候,希望在另一个方向保留原生的滚动(比如轮播图,我们希望横向模拟横向滚动,而纵向的滚动还是保留原生滚动,我们可以设置
eventPassthrough
为 vertical;相应的,如果我们希望保留横向的原生滚动,可以设置eventPassthrough
为 horizontal)。 - 备注:
eventPassthrough
的设置会导致其它一些选项配置无效,需要小心使用它。
click
- 类型:
boolean
- 默认值:
false
- 作用:BetterScroll 默认会阻止浏览器的原生 click 事件。当设置为 true,BetterScroll 会派发一个 click 事件,我们会给派发的 event 参数加一个私有属性
_constructed
,值为 true。
dblclick
- 类型:
boolean | Object
- 默认值:
false
- 作用:派发双击点击事件。当配置成 true 的时候,默认 2 次点击的延时为 300 ms,如果配置成对象可以修改
delay
。
dblclick: {
delay: 300
}
tap
- 类型:
string
- 默认值:
''
- 作用:因为 BetterScroll 会阻止原生的 click 事件,我们可以设置 tap 为 ‘tap’,它会在区域被点击的时候派发一个 tap 事件,你可以像监听原生事件那样去监听它。
bounce
- 类型:
boolean | Object
- 默认值:
true
- 作用:当滚动超过边缘的时候会有一小段回弹动画。设置为 true 则开启动画。
bounce: {
top: true,
bottom: true,
left: true,
right: true
}
bounce
可以支持关闭某些边的回弹效果,可以设置对应边的 key
为 false
即可。
TIP
如果想要便捷的设置所有边为 true 或者 false,只需要设置 bounce
为 true 或 false 即可。
bounceTime
- 类型:
number
- 默认值:
800
(单位ms) - 作用:设置回弹动画的动画时长。
momentum
- 类型:
boolean
- 默认值:
true
- 作用:当快速在屏幕上滑动一段距离的时候,会根据滑动的距离和时间计算出动量,并生成滚动动画。设置为 true 则开启动画。
momentumLimitTime
- 类型:
number
- 默认值:
300
(单位ms) - 作用:只有在屏幕上快速滑动的时间小于
momentumLimitTime
,才能开启 momentum 动画。
momentumLimitDistance
- 类型:
number
- 默认值:
15
(单位px) - 作用:只有在屏幕上快速滑动的距离大于
momentumLimitDistance
,才能开启 momentum 动画。
swipeTime
- 类型:
number
- 默认值:
2500
(单位ms) - 作用:设置 momentum 动画的动画时长。
swipeBounceTime
- 类型:
number
- 默认值:
500
(单位ms) - 作用:设置当运行 momentum 动画时,超过边缘后的回弹整个动画时间。
deceleration
- 类型:
number
- 默认值:
0.0015
- 作用:表示 momentum 动画的减速度。
flickLimitTime
- 类型:
number
- 默认值:
200
(单位ms) - 作用:有的时候我们要捕获用户的轻拂动作(短时间滑动一个较短的距离)。只有用户在屏幕上滑动的时间小于
flickLimitTime
,才算一次轻拂。
flickLimitDistance
- 类型:
number
- 默认值:
100
(单位px) - 作用:只有用户在屏幕上滑动的距离小于
flickLimitDistance
,才算一次轻拂。
resizePolling
- 类型:
number
- 默认值:
60
(单位ms) - 作用:当窗口的尺寸改变的时候,需要对 BetterScroll 做重新计算,为了优化性能,我们对重新计算做了延时。60ms 是一个比较合理的值。
probeType
- 类型:
number
- 默认值:
0
- 可选值:
1|2|3
- 作用:决定是否派发 scroll 事件,对页面的性能有影响,尤其是在
useTransition
为 true 的模式下。
// 派发 scroll 的场景分为两种:
// 1. 手指作用在滚动区域(content DOM)上;
// 2. 调用 scrollTo 方法或者触发 momentum 滚动动画(其实底层还是调用 scrollTo 方法)
// 对于 v2.1.0 版本,对 probeType 做了一次统一
// 1. probeType 为 0,在任何时候都不派发 scroll 事件,
// 2. probeType 为 1,仅仅当手指按在滚动区域上,每隔 momentumLimitTime 毫秒派发一次 scroll 事件,
// 3. probeType 为 2,仅仅当手指按在滚动区域上,一直派发 scroll 事件,
// 4. probeType 为 3,任何时候都派发 scroll 事件,包括调用 scrollTo 或者触发 momentum 滚动动画
preventDefault
- 类型:
boolean
- 默认值:
true
- 作用:当事件派发后是否阻止浏览器默认行为。这个值应该设为 true,除非你真的知道你在做什么,通常你可能用到的是
preventDefaultException
。
preventDefaultException
- 类型:
Object
- 默认值:
{ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO)$/}
- 作用:BetterScroll 会阻止原生的滚动,这样也同时阻止了一些原生组件的默认行为。这个时候我们不能对这些元素做 preventDefault,所以我们可以配置 preventDefaultException。默认值
{tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO)$/}
表示标签名为 input、textarea、button、select、audio 这些元素的默认行为都不会被阻止。 - 备注:这是一个非常有用的配置,它的 key 是 DOM 元素的属性值,value 可以是一个正则表达式。比如我们想配一个 class 名称为 test 的元素,那么配置规则为
{className:/(^|\s)test(\s|$)/}
。
tagException
- 类型:
Object
- 默认值:
{ tagName: /^TEXTAREA$/ }
- 作用:如果 BetterScroll 嵌套了 textarea 等表单元素,往往用户的预期应该是滑动 textarea 不应该引起 bs 滚动,也就是如果操纵的 DOM(eg:textarea 标签) 命中了配置的规则,bs 不会滚动。
- 备注:这是一个非常有用的配置,它的 key 是 DOM 元素的属性值,value 可以是一个正则表达式。比如我们想配一个 classname 含有 test 类名的元素,那么配置规则为
{className:/(^|\s)test(\s|$)/}
。
HWCompositing
- 类型:
boolean
- 默认值:
true
- 作用:是否开启硬件加速,开启它会在 content 元素上添加
translateZ(1px)
来开启硬件加速从而提升动画性能,有很好的滚动效果。 - 备注:只有支持硬件加速的浏览器开启才有效果。
useTransition
- 类型:
boolean
- 默认值:
true
- 作用:是否使用 CSS3 transition 动画。如果设置为 false,则使用 requestAnimationFrame 做动画。
bindToWrapper
- 类型:
boolean
- 默认值:
false
- 作用:touchmove 事件通常会绑定到 document 上而不是滚动的容器(wrapper)上,当移动的过程中光标(通常对于 PC 场景)离开滚动的容器滚动仍然会继续,这通常是期望的。当然你也可以把 move 事件绑定到滚动的容器上,
bindToWrapper
设置为 true 即可,这样一旦移动的过程中光标离开滚动的容器,滚动会立刻停止。 - 注意:对于移动端来说,就算 touchmove 事件绑定在 wrapper 上,手指离开 wrapper,依然能移动 wrapper。
disableMouse
- 类型:
boolean
- 默认值:根据当前浏览器环境计算而来
- 作用:当在移动端环境(支持 touch 事件),disableMouse 会计算为 true,这样就不会监听鼠标相关的事件,而在 PC 环境,disableMouse 会计算为 false,就会监听鼠标相关事件。
disableTouch
- 类型:
boolean
- 默认值:根据当前浏览器环境计算而来
- 作用:当在移动端环境(支持 touch 事件),disableTouch 会计算为 false,监听 touch 相关的事件,而在 PC 环境,disableTouch 会计算为 true,不会监听 touch 相关事件。
WARNING
考虑到用户的一些特定场景,比如在平板电脑需要支持 touch 事件,平板电脑接入鼠标又得支持 mouse 事件,那么实例化 BetterScroll 需要如下配置:
let bs = new BScroll('.wrapper', {
disableMouse: false,
disableTouch: false
})
由于不同设备、不同浏览器环境的底层实现逻辑不同,BetterScroll 内部计算是否监听 touch 还是 mouse 事件可能会有判断失误,因此你可以根据以上的选项配置来解决这类问题。
autoBlur
- 类型:
boolean
- 默认值:
true
- 作用:在滚动之前会让当前激活的元素(input、textarea)自动失去焦点。
stopPropagation
- 类型:
boolean
- 默认值:
false
- 作用:是否阻止事件冒泡。多用在嵌套 scroll 的场景。
bindToTarget
- 类型:
boolean
- 默认值:
false
- 作用:将 touch 或者 mouse 事件绑定在
content
元素而不是容器wrapper
上,多用于 movable 场景。
autoEndDistance
- 类型:
number
- 默认值:
5
- 作用:当手指操作幅度过大,滑出视口导致可能没有触发 touchend 事件,因此 autoEndDistance 的作用就是当手指即将脱离当前视口的时候,自动调用 touchend 事件。默认距离边界 5px 的时候,结束滚动。
outOfBoundaryDampingFactor
- 类型:
number
- 默认值:
1 / 3
- 作用:当超过边界的时候,进行阻尼行为,阻尼因子越小,阻力越大,取值范围:[0, 1]。
specifiedIndexAsContent 2.0.4
- 类型:
number
- 默认值:
0
- 作用:指定
wrapper
对应索引的子元素作为content
,默认情况下 BetterScroll 采用的是wrapper
的第一个子元素作为 content。
<div class="wrapper">
<div class="content1">
<div class="conten1-item">1.1</div>
<div class="conten1-item">1.2</div>
</div>
<div class="content2">
<div class="conten2-item">2.1</div>
<div class="conten2-item">2.2</div>
</div>
</div>
// 针对以上 DOM 结构,在 BetterScroll 版本 <= 2.0.3,内部只会使用 wrapper.children[0],也就是 div.content1 作为 content
// 当 版本 >= 2.0.4 的时候,可以通过 specifiedIndexAsContent 配置项来指定 content
let bs = new BScroll('.wrapper', {
specifiedIndexAsContent: 1 // 使用 div.content2 作为 BetterScroll 的 content
})
API
如果想要彻底了解 BetterScroll,就需要了解其实例的常用属性、灵活的方法以及提供的事件与钩子。
属性
有时候我们想基于 BetterScroll 做一些扩展,需要对 BetterScroll 的一些属性有所了解,下面介绍几个常用属性。
x
- 类型:number
- 作用:bs 横轴坐标。
y
- 类型:number
- 作用:bs 纵轴坐标。
maxScrollX
- 类型:number
- 作用:bs 最大横向滚动位置。
- 备注:bs 横向滚动的位置区间是 [minScrollX, maxScrollX],并且 maxScrollX 是负值。
#minScrollX
- 类型:number
- 作用:bs 最小横向滚动位置。
- 备注:bs 横向滚动的位置区间是 [minScrollX, maxScrollX],并且 minScrollX 是正值。
maxScrollY
- 类型:number
- 作用:bs 最大纵向滚动位置。
- 备注:bs 纵向滚动的位置区间是 [minScrollY, maxScrollY],并且 maxScrollY 是负值。
minScrollY
- 类型:number
- 作用:bs 最小纵向滚动位置。
- 备注:bs 纵向滚动的位置区间是 [minScrollY, maxScrollY],并且 minScrollY 是正值。
movingDirectionX
- 类型:number
- 作用:判断 bs 滑动过程中的方向(左右)。
- 备注:-1 表示手指从左向右滑,1 表示从右向左滑,0 表示没有滑动。
movingDirectionY
- 类型:number
- 作用:判断 bs 滑动过程中的方向(上下)。
- 备注:-1 表示手指从上往下滑,1 表示从下往上滑,0 表示没有滑动。
directionX
- 类型:number
- 作用:判断 bs 滑动结束后相对于开始滑动位置的方向(左右)。
- 备注:-1 表示手指从左向右滑,1 表示从右向左滑,0 表示没有滑动。
directionY
- 类型:number
- 作用:判断 bs 滑动结束后相对于开始滑动位置的方向(上下)。
- 备注:-1 表示手指从上往下滑,1 表示从下往上滑,0 表示没有滑动。
enabled
- 类型:boolean,
- 作用:判断当前 bs 是否处于启用状态,不再响应手指的操作。
pending
- 类型:boolean,
- 作用:判断当前 bs 是否处于滚动动画过程中。
方法
BetterScroll 提供了很多灵活的 API,当我们基于 BetterScroll 去实现一些 feature 的时候,会用到这些 API,了解它们会有助于开发更加复杂的需求。
refresh()
- 参数:无
- 返回值:无
- 作用:重新计算 BetterScroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。
scrollTo(x, y, time, easing, extraTransform)
-
参数
:
- {number} x 横轴坐标(单位 px)
- {number} y 纵轴坐标(单位 px)
- {number} time 滚动动画执行的时长(单位 ms)
- {Object} easing 缓动函数,一般不建议修改,如果想修改,参考源码中的
packages/shared-utils/src/ease.ts
里的写法 - {Object} extraTransform,只有在你想要修改 CSS transform 的一些其他属性的时候,你才需要传入此参数,结构如下:
let extraTransform = { // 起点的属性 start: { scale: 0 }, // 终点的属性 end: { scale: 1.1 } } bs.scrollTo(0, -60, 300, undefined, extraTransform)
-
返回值:无
-
作用:相对于当前位置偏移滚动 x,y 的距离。
scrollBy(x, y, time, easing)
-
参数
:
- {number} x 横轴变化量(单位 px)
- {number} y 纵轴变化量(单位 px)
- {number} time 滚动动画执行的时长(单位 ms)
- {Object} easing 缓动函数,一般不建议修改,如果想修改,参考源码中的
packages/shared-utils/src/ease.ts
里的写法
-
返回值:无
-
作用:相对于当前位置偏移滚动 x,y 的距离。
scrollToElement(el, time, offsetX, offsetY, easing)
-
参数
:
- {DOM | string} el 滚动到的目标元素, 如果是字符串,则内部会尝试调用 querySelector 转换成 DOM 对象。
- {number} time 滚动动画执行的时长(单位 ms)
- {number | boolean} offsetX 相对于目标元素的横轴偏移量,如果设置为 true,则滚到目标元素的中心位置
- {number | boolean} offsetY 相对于目标元素的纵轴偏移量,如果设置为 true,则滚到目标元素的中心位置
- {Object} easing 缓动函数,一般不建议修改,如果想修改,参考源码中的
packages/shared-utils/src/ease.ts
里的写法
-
返回值:无
-
作用:滚动到指定的目标元素。
stop()
- 参数:无
- 返回值:无
- 作用:立即停止当前运行的滚动动画。
enable()
- 参数:无
- 返回值:无
- 作用:启用 BetterScroll, 默认 开启。
disable()
- 参数:无
- 返回值:无
- 作用:禁用 BetterScroll,DOM 事件(如 touchstart、touchmove、touchend)的回调函数不再响应。
destroy()
- 参数:无
- 返回值:无
- 作用:销毁 BetterScroll,解绑事件。
on(type, fn, context)
-
参数
:
- {string} type 事件名
- {Function} fn 回调函数
- {Object} context 函数执行的上下文环境,默认是 this
-
返回值:无
-
作用:监听当前实例上的钩子函数。如:scroll、scrollEnd 等。
-
示例:
import BScroll from '@better-scroll/core'
let scroll = new BScroll('.wrapper', {
probeType: 3
})
function onScroll(pos) {
console.log(`Now position is x: ${pos.x}, y: ${pos.y}`)
}
scroll.on('scroll', onScroll)
once(type, fn, context)
-
参数
:
- {string} type 事件名
- {Function} fn 回调函数
- {Object} context 函数执行的上下文环境,默认是 this
-
返回值:无
-
作用:监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。
off(type, fn)
-
参数
:
- {string} type 事件名
- {Function} fn 回调函数
-
返回值:无
-
作用:移除自定义事件监听器。只会移除这个回调的监听器。
-
示例:
import BScroll from '@better-scroll/core'
let scroll = new BScroll('.wrapper', {
probeType: 3
})
function handler() {
console.log('bs is scrolling now')
}
scroll.on('scroll', handler)
scroll.off('scroll', handler)
事件 VS 钩子
基于 2.x 的架构设计,以及对 1.x 事件的兼容,我们延伸出两个概念 ——『事件』以及『钩子』。从本源上来说它们都是属于 EventEmitter
实例,只是叫法不一样。下面我们从节选的源码来讲解一下:
export default BScrollCore extends EventEmitter {
hooks: EventEmitter
}
-
BScrollCore
本身继承了 EventEmitter。它派发出来的,我们都称之为『事件』。
import BScroll from '@better-scroll/core' let bs = new BScroll('.wrapper', {}) // 监听 bs 的 scroll 事件 bs.on('scroll', () => {}) // 监听 bs 的 refresh 事件 bs.on('refresh', () => {})
-
BScrollCore.hooks
hooks 也是 EventEmitter 的实例。它派发出来的,我们都称之为『钩子』。
import BScroll from '@better-scroll/core' let bs = new BScroll('.wrapper', {}) // 监听 bs 的 refresh 钩子 bs.hooks.on('refresh', () => {}) // 监听 bs 的 enable 钩子 bs.hooks.on('enable', () => {})
相信现在大家对两者有了更好的区分吧,『事件』是为了 1.x 的兼容考虑,用户一般关注的是事件的派发,但是如果要编写一款插件,你应该更加关注『钩子』。
事件
在 2.0 当中,BetterScroll 事件与 1.x 的事件是拉齐的,只有 BetterScroll 会派发『事件』,如果你在编写插件的时候需要暴露事件,你也应该通过 BetterScroll 来派发,详细的教程看这,目前的事件分为下面几种:
-
refresh
- 触发时机:BetterScroll 重新计算
import BetterScroll from '@better-scroll/core' const bs = new BetterScroll('.wrapper', {}) bs.on('refresh', () => {})
-
enable
- 触发时机:BetterScroll 启用,开始响应用户交互
bs.on('enable', () => {})
-
disable
- 触发时机:BetterScroll 禁用,不再响应用户交互
bs.on('disable', () => {})
-
beforeScrollStart
- 触发时机:用户手指放在滚动区域的时候
bs.on('beforeScrollStart', () => {})
-
scrollStart
- 触发时机:content 元素满足滚动条件,即将开始滚动
bs.on('scrollStart', () => {})
-
scroll
- 触发时机:正在滚动
bs.on('scroll', (position) => { console.log(position.x, position.y) })
-
scrollEnd
- 触发时机:滚动结束,或者让一个正在滚动的 content 强制停止
bs.on('scrollEnd', () => {})
-
scrollCancel
- 触发时机:滚动取消
bs.on('scrollCancel', () => {})
-
touchEnd
- 触发时机:用户手指离开滚动区域
bs.on('touchEnd', () => {})
-
flick
- 触发时机:用户触发轻拂操作
bs.on('flick', () => {})
-
destroy
- 触发时机:BetterScroll 销毁
bs.on('destroy', () => {})
-
contentChanged 2.0.4
- 触发时机:在调用
bs.refresh()
,探测到 content DOM 变成了其他元素的时候
// bs 版本 >= 2.0.4 bs.on('contentChanged', (newContent: HTMLElement) => {})
- 触发时机:在调用
以下的事件必须注册括号中的插件才会派发:
-
alterOptions(*mouse-wheel*)
- 触发时机:滚轮滚动开始
import BetterScroll from '@better-scroll/core' import MouseWheel from '@better-scroll/mouse-wheel' BetterScroll.use(MouseWheel) const bs = new BetterScroll('.wrapper', { mouseWheel: true }) bs.on('alterOptions', (mouseWheelOptions) => { /** * mouseWheelOptions.speed:鼠标滚轮滚动的速度 * mouseWheelOptions.invert:滚轮滚动和 BetterScroll 滚动的方向是否一致 * mouseWheelOptions.easeTime:滚动动画的缓动时长。 * mouseWheelOptions.discreteTime:触发 wheelEnd 的间隔时长 * mouseWheelOptions.throttleTime:滚轮滚动是高频率的动作,因此可以通过 throttleTime 来限制触发频率 * mouseWheelOptions.dampingFactor:阻尼因子,当超出边界会施加阻力 **/ })
-
mousewheelStart(*mouse-wheel*)
- 触发时机:滚轮滚动开始
import BetterScroll from '@better-scroll/core' import MouseWheel from '@better-scroll/mouse-wheel' BetterScroll.use(MouseWheel) const bs = new BetterScroll('.wrapper', { mouseWheel: true }) bs.on('mousewheelStart', () => {})
-
mousewheelMove(*mouse-wheel*)
- 触发时机:滚轮滚动中
bs.on('mousewheelMove', () => {})
-
mousewheelEnd(*mouse-wheel*)
- 触发时机:滚轮滚动结束
bs.on('mousewheelEnd', () => {})
-
pullingDown(*pull-down*)
- 触发时机:当顶部下拉距离超过阈值
import BetterScroll from '@better-scroll/core' import Pulldown from '@better-scroll/pull-down' BetterScroll.use(Pulldown) const bs = new BetterScroll('.wrapper', { pullDownRefresh: true }) bs.on('pullingDown', () => { await fetchData() bs.finishPullDown() })
-
pullingUp(*pull-up*)
- 触发时机:当底部下拉距离超过阈值
import BetterScroll from '@better-scroll/core' import Pullup from '@better-scroll/pull-up' BetterScroll.use(Pullup) const bs = new BetterScroll('.wrapper', { pullUpLoad: true }) bs.on('pullingUp', () => { await fetchData() bs.finishPullUp() })
-
slideWillChange(*slide*)
- 触发时机:轮播图即将要切换 Page
import BetterScroll from '@better-scroll/core' import Slide from '@better-scroll/slide' BetterScroll.use(Slide) const bs = new BetterScroll('.wrapper', { slide: true, momentum: false, bounce: false, probeType: 2 }) bs.on('slideWillChange', (page) => { // 即将要切换的页面 console.log(page.pageX, page.pageY) })
-
beforeZoomStart(*zoom*)
- 触发时机:双指接触缩放元素时
import BetterScroll from '@better-scroll/core' import Zoom from '@better-scroll/zoom' BetterScroll.use(Zoom) const bs = new BetterScroll('.wrapper', { zoom: true }) bs.on('beforeZoomStart', () => {})
-
zoomStart(*zoom*)
- 触发时机:双指缩放距离超过最小阈值
bs.on('zoomStart', () => {})
-
zooming(*zoom*)
- 触发时机:双指缩放行为正在进行时
bs.on('zooming', ({ scale }) => { // scale 当前 scale })
-
zoomEnd(*zoom*)
- 触发时机:双指缩放行为结束后
bs.on('zoomEnd', ({ scale }) => {})
#钩子
钩子是 2.0 版本延伸出来的概念,它的本质与事件相同,都是 EventEmitter 实例,也就是典型的订阅发布模式。BScrollCore 作为一个最小的滚动单元,内部也是存在非常多的功能类,每个功能类都有一个叫 hooks 的属性,它架起了不同类之间沟通的桥梁。如果你要编写一个复杂的插件,钩子是必须需要掌握的内容。
-
BScrollCore.hooks
-
beforeInitialScrollTo
-
触发时机:初始化加载完插件,需要滚动到指定位置
-
参数
:position 对象
{ x: number, y: number }
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) bs.hooks.on('beforeInitialScrollTo', (postion) => { postion.x = 0 position.y = -200 // 初始化滚动至 -200 的位置 })
-
-
refresh
- 触发时机:重新计算 BetterScroll
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) bs.hooks.on('refresh', () => { console.log('refreshed') })
-
enable
- 触发时机:启用 BetterScroll,响应用户行为
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) bs.hooks.on('enable', () => { console.log('enabled') })
-
disable
- 触发时机:禁用 BetterScroll,不再响应用户行为
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) bs.hooks.on('disable', () => { console.log('disabled') })
-
destroy
- 触发时机:销毁 BetterScroll
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) bs.hooks.on('destroy', () => { console.log('destroyed') })
-
contentChanged 2.0.4
- 触发时机:在调用
bs.refresh()
,探测到 content DOM 变成了其他元素的时候 - 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) // bs 版本 >= 2.0.4 bs.hooks.on('contentChanged', (newContent: HTMLElement) => { console.log(newContent) })
- 触发时机:在调用
-
-
ActionsHandler.hooks
-
beforeStart
- 触发时机:刚响应 touchstart 事件,还未记录手指在屏幕点击的位置
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actionsHandler.hooks hooks.on('beforeStart', (event) => { console.log(event.target) })
-
start
- 触发时机:记录完手指在屏幕点击的位置,即将触发 touchmove
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actionsHandler.hooks hooks.on('start', (event) => { console.log(event.target) })
-
move
-
触发时机:响应 touchmove 事件,记录完手指在屏幕点击的位置
-
参数
:拥有如下属性的对象
{ number } deltaX
:x 方向的手指偏移量{ number } deltaY
:y 方向的手指偏移量{ event } e
:event 事件对象
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actionsHandler.hooks hooks.on('move', ({ deltaX, deltaY, e }) => {})
-
-
end
- 触发时机:响应 touchend 事件
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actionsHandler.hooks hooks.on('end', (event) => {})
-
click
- 触发时机:触发 click 事件
- 参数:event 事件对象
-
-
ScrollerActions.hooks
-
start
- 触发时机:记录完所有的滚动初始信息
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('start', (event) => { console.log(event.target) })
-
beforeMove
- 触发时机:在检验是否是合法的滚动之前
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('beforeMove', (event) => { console.log(event.target) })
-
scrollStart
- 触发时机:校验是合法的滚动,并且即将开始滚动
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('scrollStart', () => {})
-
scroll
- 触发时机:正在滚动
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('scroll', () => {})
-
beforeEnd
- 触发时机:刚执行 touchend 事件回调,但是还未更新最终位置
- 参数:event 事件对象
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('beforeEnd', (event) => { console.log(event) })
-
end
-
触发时机:刚执行 touchend 事件回调并且更新滚动方向
-
参数
:两个参数,第一个是 event 事件对象,第二个是当前位置
{ event } e
:事件对象{ x: number, y: number } postion
:当前位置
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('end', (e, postion) => { console.log(e) })
-
-
scrollEnd
-
触发时机:滚动即将结束,但还需要校验一次滚动行为是否触发了 flick、momentum 行为。
-
参数
:两个参数,第一个是当前位置,第二个是动画时长
{ x: number, y: number } postion
:当前位置{ number } duration
:动画时长
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.actions.hooks hooks.on('beforeEnd', (pos, duration) => { console.log(pos) })
-
-
-
Behavior.hooks
-
beforeComputeBoundary
-
触发时机:即将计算滚动边界
-
参数
:boundary 对象
{ minScrollPos: number, maxScrollPos: number } boundary
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.scrollBehaviorX.hooks hooks.on('beforeComputeBoundary', () => {})
-
-
computeBoundary
- 触发时机:计算滚动边界
- 示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.scrollBehaviorX.hooks hooks.on('computeBoundary', (boundary) => { console.log(boundary.minScrollPos) // 上边界最大值,正的越多,下拉的幅度越大 console.log(boundary.maxScrollPos) // 下边界最小值,负的越多,滚的越远 })
-
momentum
-
触发时机:满足触发 momentum 动量动画条件,并且在计算之前
-
参数
:两个参数,第一个是 momentumData 对象,第二个是滚动偏移量
{ destination: number, duration: number, rate: number} momentumData
:destination 是目标位置,duration 是缓动时长,rate 是斜率{ number } distance
:触发 momentum 的滚动偏移量
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.scrollBehaviorX.hooks hooks.on('momentum', (momentumData, distance) => {})
-
-
end
-
触发时机:不满足触发 momentum 动量动画条件
-
参数
:momentumInfo 对象
{ destination: number, duration: number} momentumInfo
:destination 是目标位置,duration 是缓动时长
-
示例
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.scrollBehaviorX.hooks hooks.on('end', (momentumInfo) => { console.log(momentumInfo.destination) console.log(momentumInfo.duration) })
-
-
-
Animation.hooks(useTransition: false)
-
forceStop
-
触发时机:强制让一个滚动的 bs 停止
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
move
-
触发时机:滚动进行中
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
end
-
触发时机:滚动结束
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
-
Translater.hooks
-
beforeTranslate
-
触发时机:在修改 content 元素的 transform style 之前,zoom 插件监听了钩子
-
参数
:第一个是 transformStyle 数组,第二个是 point 对象
{ ['translateX(0px)'|'translateY(0px)'] } transformStyle
:当前 transform 对应的属性值{ x: number, y: number } point
:x 对应 translateX 的值,y 对应 translateY 的值
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.translater.hooks hooks.on('beforeTranslate', (transformStyle, point) => { transformStyle.push('scale(1.2)') console.log(transformStyle) // ['translateX(0px)', 'translateY(0px)', 'scale(1.2)'] console.log(point) // { x: 0, y: 0 } })
-
-
translate
-
触发时机:修改 content 元素的 transform style 之后,wheel 插件监听了钩子
-
参数
:point 对象
{ x: number, y: number } point
:x 对应 translateX 的值,y 对应 translateY 的值
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.translater.hooks hooks.on('translate', (point) => { console.log(point) // { x: 0, y: 0 } })
-
-
-
Transition.hooks(useTransition: true)
-
forceStop
-
触发时机:强制让一个正在做动画的 bs 停止
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
move
-
触发时机:滚动进行中
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
end
-
触发时机:滚动结束
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
time
-
触发时机:CSS3 transition 开始之前,wheel 插件监听了该钩子
-
参数
:CSS3 transition duration
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.animater.hooks hooks.on('time', (duration) => { console.log(duration) // 800 })
-
-
timeFunction
-
触发时机:CSS3 transition 开始之前,wheel 插件监听了该钩子
-
参数
:CSS3 transition-timing-function
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.animater.hooks hooks.on('timeFunction', (easing) => { console.log(easing) // cubic-bezier(0.1, 0.7, 1.0, 0.1) })
-
-
-
Scroller.hooks
-
beforeStart 同
ScrollerActions.hooks.start
-
beforeMove 同
ScrollerActions.hooks.beforeMove
-
beforeScrollStart 同
ScrollerActions.hooks.start
-
scrollStart 同
ScrollerActions.hooks.scrollStart
-
scroll
-
触发时机:滚动进行中
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
beforeEnd 同
ScrollerActions.hooks.beforeEnd
-
touchEnd
- 触发时机:用户手指离开滚动区域
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('touchEnd', () => { console.log('your finger has leave') })
-
end
- 触发时机:touchEnd 之后,校验 click 之前触发,pull-down 插件基于这个钩子实现
- 参数:position 对象
{ x: number, y: number } position
:当前位置
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('end', (position) => { console.log(position.x) console.log(position.y) })
-
scrollEnd
-
触发时机:滚动结束
-
参数
:position 对象
{ x: number, y: number } position
:当前坐标值
-
-
resize
- 触发时机:window 尺寸发生改变
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('resize', () => { console.log("window's size has changed") })
-
flick
- 触发时机:探测到手指轻拂动作
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('flick', () => {})
-
scrollCancel
- 触发时机:滚动取消或者未发生
-
momentum
-
触发时机:即将进行 momentum 动量位移,slide 插件监听了该钩子
-
参数
:scrollMetaData 对象
{ time: number, easing: EaseItem, newX: number, newY: number }
:time 是动画时长,easing是缓动函数,newX 和 newY 是终点
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('momentum', (scrollMetaData) => { scrollMetaData.newX = 0 scrollMetaData.newY = -200 })
-
-
scrollTo
-
触发时机:调用 bs.scrollTo 方法的时候触发
-
参数
:endPoint 对象
{ x: number, y: number } endPoint
:终点坐标值
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('scrollTo', (endPoint) => { console.log(endPoint.x) console.log(endPoint.y) }) bs.scrollTo(0, -200)
-
-
scrollToElement
-
触发时机:调用 bs.scrollToElement 方法的时候触发,wheel 插件监听了该钩子
-
参数
:第一个是目标 DOM 对象,第二个是终点的坐标
{ HTMLElment } el
{ top: number, left: number } postion
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('scrollToElement', (el, pos) => { console.log(el) console.log(pos.left) console.log(pos.top) }) bs.scrollToElement('.some-item', 300, true, true)
-
-
beforeRefresh
- 触发时机:在 behavior 计算边界之前,slide 插件监听了该钩子
import BScroll from '@better-scroll/core' const bs = new BScroll('.wrapper', {}) const hooks = bs.scroller.hooks hooks.on('beforeRefresh', () => {})
-