Scroller 滚动组件 3.0.0

滚动组件,用来提供滚动容器。

  • 提供了横向滚动和纵向滚动。
  • 提供了『下拉刷新』和『加载更多』功能。
  • 提供了 transitionrequestAnimationFrame 两种实现滚动的方式。
  • 提供了 transformposition:absolute 两种实现位移的方式。

确定高度:Scroller 默认提供一个纵向滚动区域,该区域必须有一个确定的高度才能正常工作,因为它实际上就是将一系列不确定高度的子组件(div.scroller)装进一个确定高度的容器(div.yo-scroller)。实现确定高度的方式有很多种:flex,指定高度,position: absolute 等等。

内容容器:作为一个滚动组件,Scroller 会创建一个 div 作为滚动容器。如果 Scroller 的子元素只有一个,则会把这个子元素当做内容容器;否则,会创建一个 div 作为内容容器。

使用说明

引用方式

import { Scroller } from '$yo-component';

// 如果你的项目中未使用最新的 ykit-config-yo 插件,可能无法使用上面这个语法糖
// 你仍然可以通过下面这种方式来引用
import Scroller from 'yo3/component/scroller';

基本用法

Scroller 默认提供一个纵向滚动区域。该区域必须是有高度的,你可以通过以下几种方式来实现:

1. 直接设置 Scroller 的高度
<Scroller style={{ height: '400px' }}>
    <h1>这是内容区域</h1>
</Scroller>
2. 通过 flex 来设置高度
<div className="yo-flex">
    <Scroller extraClass="flex">
        <h1>这是内容区域</h1>
    </Scroller>
</div>
3. 通过 position: absolute 来设置高度
<Scroller style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
  <h1>这是内容区域</h1>
</Scroller>

当然,为了方便 Scroller 组件中内置了 yo-scroller-fullscreen 样式类,可以直接使用达到上面的效果:

<Scroller extraClass="yo-scroller-fullscreen">
  <h1>这是内容区域</h1>
</Scroller>

横向滚动

Scroller 可以提供一个横向滚动区域,只需要将 scrollX 设置为 truescrollY 设置为 false 即可。

<Scroller
  scrollX={true}
  scrollY={false}
>
  <h1>这是内容区域</h1>
</Scroller>

下拉刷新和加载更多

Scroller 提供了下拉刷新和加载更多的功能,这两个功能只支持纵向滚动。这两个功能常常在 List 组件中使用,查看List组件中的用法

1. 下拉刷新
  • 功能:在滚动到 Scroller 顶部之后,继续滚动一段距离就会触发 下拉刷新 功能。该功能可以用来刷新 Scroller 中的内容。
  • 使用:
    1. 设置 usePullRefresh 参数为 true
    2. 通过 onRefresh 方法监听触发刷新状态(即:变成加载中状态)的回调;
    3. 调用 Scroller 实例的 stopRefreshing 方法来停止加载中状态,该方法的第一个参数为一个 bool 值,用来告诉 Scroller 是否刷新成功。 如果为 true,会显示『加载成功』;如果为 false,会显示『加载失败』。
<Scroller
  ref="scroller"
  extraClass="yo-scroller-fullscreen"
  usePullRefresh={true}
  onRefresh={() => {
    // 刷新数据 start
    // ...
    // 刷新数据 end
    this.refs.scroller.stopRefreshing(true); // 这个调用也可以放在异步操作的回调里之后
  }}
>
  <h1>这是内容区域</h1>
</Scroller>
2. 加载更多
  • 功能:在滚动到 Scroller 底部之后,继续滚动一段距离就会触发 加载更多 功能。该功能可以用来加载 Scroller 中更多的内容,比如:查看详情。
  • 使用:
    1. 设置 useLoadMore 参数为 true
    2. 通过 onLoad 方法监听触发加载状态(即:变成加载中状态)的回调;
    3. 调用 Scroller 实例的 stopLoading 方法来停止加载中状态,该方法的第一个参数为一个 bool 值,用来告诉 Scroller 后面是否还有更多数据。 如果为 false 会显示『没有更多了...』。
<Scroller
  ref="scroller"
  extraClass="yo-scroller-fullscreen"
  useLoadMore={true}
  onLoad={() => {
    // 加载数据 start
    // ...
    // 加载数据 end
    this.refs.scroller.stopLoading(true); // 这个调用也可以放在异步操作的回调里之后
  }}
>
  <h1>这是内容区域</h1>
</Scroller>

滚动特性

Scroller 不仅提供了滚动容器,也提供了相关的滚动特性。

  • 禁止滚动:disabled
  • 弹性滚动:bounce 滚动是否能够超出屏幕范围
  • 惯性滚动:momentum 在松手之后有一定的速度,是否能够继续滚动一段距离
<Scroller
  disabled={false}
  bounce={false}
  momentum={false}
>
  <h1>这是内容区域</h1>
</Scroller>

滚动到某一位置

Scroller 提供了 scrollTo(x, y, time) 方法来滚动到某个位置。

  • x:横向目标位置
  • y:纵向目标位置
  • time:滚动动画时间,单位 ms,默认为 0
<Scroller ref="scroller">
  <h1>这是内容区域</h1>
</Scroller>
this.refs.scroller.scrollTo(0, -100, 300);

监听滚动事件

Scroller 提供了 onScroll 方法来监听滚动事件。一旦设置了这个回调,会强制使用 requestAnimationFrame 来实现滚动动画(包括:回弹、惯性滚动和 scrollTo 方法的动画),即使设置 useTransition 属性为 true。 这样会导致 Scroller 的性能变差,请谨慎使用。

<Scroller
  onScroll={(evt) => {
    console.log(evt.contentOffset.x); // 当前横向位移
    console.log(evt.contentOffset.y); // 当前纵向位移
  }}
>
  <h1>这是内容区域</h1>
</Scroller>
属性

extraClass { String } #

为组件根节点提供额外的class。

默认值: ''

containerExtraClass { String } #

为组件中的内容容器提供额外的class。

默认值: ''

containerExtraStyle { String } 3.0.6 #

为组件中的内容容器提供额外的style,主要用于横向滚动时,动态设置容器的宽度。

默认值: {}

contentOffset { {x: Number, y: Mumber} } #

组件中内容的初始位移,这个属性变化时,会重置内容的位移。

默认值: {x: 0, y: 0}

contentInset { Number } 3.0.13 #

内容区域周围的留白,目前仅支持 bottom。主要用于适配 iPhoneX,在下方留出一定间隙。有『加载更多』时,显示在『加载更多』的下方。可以通过设置背景色来改变留白的颜色。

默认值: {bottom:0}

stickyOffset { Number } 3.0.6 #

吸顶容器偏移,如果你希望吸顶容器不位于top:0的位置,可以修改这个属性。

默认值: 0

disabled { Bool } #

是否禁止滚动,默认允许滚动。

默认值: false

scrollX { Bool } #

是否开启横向滚动,默认关闭。

默认值: false

scrollY { Bool } #

是否开启纵向滚动,默认开启。

默认值: true

directionLockThreshold { Number } #

只允许单向滚动的时候,会根据这个阀值来判定响应哪个方向上的位移:某一方向位移减去另一个方向位移超过阀值,就会判定为这个方向的滚动。

一个常见的示例是:在一个纵向滚动的 Scroller 中嵌套一个横向滚动的 Scroller。此时,如果斜着(约45°)滚动,则内层的 Scroller 会先响应, 但是不会锁定,触摸事件会向冒泡到外层的 Scroller,导致外层的 Scroller 也会响应。此时将 directionLockThreshold 设置成 0,保证不管向哪个方向滚动, Scroller 都会锁定方向而不向外冒泡,就不会出现同时响应的问题了。

默认值: 5

momentum { Bool } #

是否允许惯性滚动。当设置为 true,手指离开时,如果还有速度会继续滚动一段距离;当设置为 false ,手指离开时会立即停止滚动。

默认值: true

bounce { Bool } #

当滚动超出内容范围时,是否可以继续滚动一截。

默认值: true

bounceTime { Number } #

当弹性滚动一截之后,回到滚动范围内位置的时间,单位为毫秒(ms)。

默认值: 600

bounceEasing { Object } #

弹性回滚动画。

Scroller 提供了五种默认的动画函数:quadratic, circular, back, bounce, elastic,可以通过 Scroller.ease.xxx 来使用。

用户也可以自定义动画对象,比如:

{ style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', fn: function (k) { return k * ( 2 - k ); } }

默认值: Scroller.ease.circular

useTransition { Bool } #

如果设置为true,会使用transition来实现滚动效果;如果设置为false,会使用requestAnimationFrame来实现。

默认值: true

useTransform { Bool } #

如果设置为true,会使用transform来实现位移;如果设置为false,会使用left和top来实现位移(position: absolute)。

默认值: true

onScroll { Function } #

(event) => void

滚动事件的回调。一旦设置了这个回调,为了能够监听滚动事件,会将useTransition属性强制设置为false,会由此带来一定的性能牺牲。

方法参数:

参数名 类型 描述 支持版本
event e 滚动事件的回调,结构为: {contentOffset: {x: x, y: y}}

onScrollEnd { Function } #

(event) => void

滚动结束之后的回调。不管是不是 transition 的滚动,都会触发。

方法参数:

参数名 类型 描述 支持版本
event e 滚动结束之后的回调,结构为: {contentOffset: {x: x, y: y}}

HWCompositing { Bool } #

是否开启硬件加速

默认值: true

preventDefault { Bool } #

是否需要在Scroller容器上对所有的触摸事件(touchstart/touchmove/touchend/touchcancel)调用preventDefault。 这个属性的默认值为true,这是为了避免一些安卓的兼容性问题。如果你发现一些默认效果没有被触发(例如输入框的blur),可以尝试设置这个属性为false。

usePullRefresh { Bool } #

是否开启下拉刷新功能

默认值: false hasPullRefresh

onRefresh { Function } #

(event) => void

下拉刷新时开始刷新的回调。

方法参数:

参数名 类型 描述 支持版本
event e 结构为: ({contentOffset: {x: x, y: y}})

pullRefreshHeight { Number } #

触发下拉刷新状态的高度(一般即为下拉刷新提示区域的高度)

默认值: 40 可以考虑不要

renderPullRefresh { Function } #

() => JSX

自定义的下拉刷新渲染函数

返回值: JSX 用来渲染

useLoadMore { Bool } #

是否开启加载更多功能.『加载更多』与『下拉刷新』略有不同,加载更多的提示区域是追加在内容区域的最后

默认值: false hasLoadMore

onLoad { Function } #

(event) => void

加载更多时开始加载的回调。

方法参数:

参数名 类型 描述 支持版本
event e 结构为: ({contentOffset: {x: x, y: y}})

loadMoreHeight { Number } #

触发加载更多状态的高度(一般即为加载更多提示区域的高度)

默认值: 40

renderLoadMore { Function } #

() => JSX

自定义的加载更多渲染函数

返回值: JSX 用来渲染

scrollWithoutTouchStart { Bool } 3.0.2 #

实验中的属性 在默认情况下一次用户触发(非调用scrollTo方法)scroller的滚动需要由touchstart事件来启动,在某些情况下,例如scroller从disable状态切换到enable状态时, 可能不能接收到这一瞬间的touchstart事件,这可能导致用户期待的滚动过程没有发生。 开启这个属性为 true 以后将允许 scroller 用 touchmove 启动滚动过程,这可以解决上述场景的问题。

默认值: true (从 3.0.17 开始,默认值从 false 改为 true)

scrollIntoView { String } 3.1.7 #

值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素

默认值: ''

方法

stopAnimate #

停止当前的滚动动画,包括:惯性滚动、回弹、ScrollTo等。

refresh #

刷新 Scroller,一般场景不推荐使用,因为当内容改变的时候,Scroller 会自动 render。

使用场景1:需要强制设置 Scroller 本身的宽高和内容容器的宽高时,可以通过refreshOption来传入宽高代替dom的宽高。

使用场景2:在某些不是通过 setState 或 Redux 等方式来改变内容导致 Scroller 不会 render 时,可以强制重新获取Scroller宽高和内容容器宽高。

方法参数:

参数名 类型 描述 必选 支持版本
refreshOption Object 刷新参数,{wrapperWidth, wrapperHeight, scrollerWidth, scrollerHeight}

refreshLazyImage 3.0.12 #

刷新 Scroller 中的 LazyImage。

使用场景:在某些不是通过 setState 或 Redux 等方式来直接改变 Scroller 的内容导致 Scroller 不会 render 时,由于内容宽高发生了变化,需要通过本方法来刷新 LazyImage 的位置信息。

scrollTo #

滚动到某个位置。

方法参数:

参数名 类型 描述 必选 支持版本
x Number 水平位移,默认值为当前水平位移
y Number 垂直位移,默认值为当前垂直位移
time Number 滚动时间,默认值为0
easing Object 滚动动画对象。参照 `bounceEasing` 参数。

resetLoadStatus 3.0.7 #

重置加载更多功能。

方法参数:

参数名 类型 描述 必选 支持版本
hasLoadMore Bool 是否能够加载更多,如果传入false,加载更多区域的文字将会变成 没有更多了,并且继续向下滚动时不会触发onLoadMore。

startRefreshing #

强制开始刷新。这个方法一般是用在切换筛选项或者关键字等场景,来达到回到顶部并且开始刷新的效果。如果是用户下拉触发 onRefresh 时,就不需要再调用这个方法了。

方法参数:

参数名 类型 描述 必选 支持版本
time Number 滚动到顶部的时间,默认为 300ms

stopRefreshing #

中止下拉刷新过程。在列表发生下拉刷新之后你应该调用这个方法去中止它(比如服务器响应已经返回的时候),否则刷新不会自动终止。

方法参数:

参数名 类型 描述 必选 支持版本
success Bool 下拉刷新是否成功,默认为 false。
config Object 停止刷新的配置项 { duration: 回到顶部的动画时间,默认是300ms delay: 成功/失败提示信息的停留时间,默认是0ms }
config.duration number 回到顶部的动画时间,默认是 300ms。
config.delay number 成功/失败提示信息的停留时间,默认是0ms 3.1.8
callback Function 回到顶部的动画执行完毕的回调。

stopLoading #

停止加载更多。

方法参数:

参数名 类型 描述 必选 支持版本
status Bool 刷新的状态。true表示加载了更多数据,false表示没有更多数据了。