List 3.0.0

列表组件,继承了Scroller的特性,有下拉刷新和加载更多功能。

除此之外,List优化了长列表的性能,在数据源较大时能够提升滚动的性能并避免内存溢出。

使用列表组件实现的组件:GroupList、Calendar、SwipeMenuList。

特别感谢大明哥(leeds.li)和她的不定高无穷列表的实现思路。

使用说明

引用方式

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

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

根节点尺寸

Scroller 组件一样,List 需要一个固定的高度才能正常工作。 你可以通过给它指定 extraClass 来扩展它的样式, 这个额外的 class 会被添加到 List 组件的根节点上。例如

.yo-list-fullscreen {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: absolute;
}
<List
  extraClass = {'yo-list-fullscreen'}
  // ...
/>

这样就可以让这个 List 撑满它的父容器。当然你也可以使用 Scroller 内置的 yo-scroller-fullscreen 样式类来实现。

数据源

List 最基础的属性是 dataSource ,通过它可以配置列表的数据源,在默认情况下,dataSource 是一个数组。 你还需要配置 renderItem 属性来指定列表项的渲染方式,示例如下:

let guid = -1;
...

<List
  dataSource={[
    {content: "元素1", key: ++guid},
    {content: "元素2", key: ++guid},
    {content: "元素3", key: ++guid},
    // ...
  ]}
  renderItem={(item,i)=>{
    return (
      <p>
        {`第${i}项的内容是${item.content}`}
      </p>
    );
  }}
/>

或者如果你的 dataSource 中的元素有 text 属性,会直接以 text 的值作为列表项的内容。

dataSource 中每个数据元素需要有一个唯一的 key 标识,这和 React 列表类型的 JSX 是一致的,这个标识会被用来优化长列表的性能,当然你也可以通过 uniqueKeyName 这个属性来指定唯一标识的键值(其默认值为 key)。

关于这个 key 的选取有多种方式,如果列表和某个后端接口相关联,那么可以使用接口返回数据中数据库 id 对应的值。如果没有类似的字段,可以使用自增的 guid 来作为 key 值, 不过这样存在的问题是即使是同样的一条数据,在 dataSource 发生变化后可能会有不同的 key ,这会造成很大的性能浪费。而如果两个列表项拥有同样的 key 值,会造成组件 渲染错乱。所以请务必谨慎选择 key 值。

使用Immutable数据结构作为数据源

除了可以使用数组作为 dataSource 以外,我们也提供了对 ImmutableJS 的支持, 你需要提供给 dataSource 属性一个 Immutable List 使用 ImmutablefromJS API 可以很方便地得到符合 dataSource 要求的数据源,下面是一个例子:

import Immutable from 'immutable';

const dataSource = Immutable.fromJS([
  { text: 'item 1', key: 0, height: 20 }, // text, key, height属性的功能没有变化
  { text: 'item 2', key: 1, height: 40 },
  // ...
]);

<List
  dataSource={dataSource}
  // ...
/>

列表项的触摸事件

可以通过 onItemTap 属性为每个列表项指定一个 tap 事件回调,可以接收三个参数 item (列表项对应的数据元素),index(列表项的 index)以及 target(当前触发 tap 事件的 dom):

<List
  ...
  onItemTap={(item,index,target) => {
    // ...
  }}
/>

你也可以使用 Touchable 组件为列表项内部的元素绑定 tap 事件,详见 Touchable 文档。

在设置了 onItemTap 属性的情况下,可以通过设置 itemTouchClass 来指定列表项的触摸反馈效果(通过在 touchstart 时给列表项添加一个 className),默认值是 item-touch 。 这个属性可以接收两种形式的值:当传入一个字符串时,会给所有的列表项绑定相同的 touchClass;传入函数时,可以根据 item 为不同的列表项定制 touchClass。 如果是一个纯展示功能的 List ,你可以设置 itemTouchClass = null 来取消触摸反馈效果。

<List
  onItemTap={...}
  itemTouchClass={'custom-active-class'} // 传入字符串
  itemTouchClass={(item,i) => { return item.activeClassName; }} // 传入函数
  // ...
/>

无穷(Infinite)模式

List 组件提供了优化长列表性能的方式:无穷模式(Infinite)。开启无穷模式以后,列表内只会保留可见区域附近的列表项,然后随着列表的滚动实时更新。 这样就可以避免列表项过多导致的滚动困难和内存溢出问题。但是由于在滚动时会做 dom 的更新操作,它的滚动性能要比静态的列表稍差。所以对于列表项不多的 List,无需开启无穷模式。

配置属性 infinite = true 即可开启无穷模式的列表。如下:

<List
  dataSource={/* a very long array... */}
  infinite={true}
  renderItem={...}
  // ...
/>

无穷模式下列表项的高度

无穷列表的运作机制有两种:指定高度和不指定高度。如果指定了列表项的高度,那么实际上所有的列表项在初始化时即可完成定位,反之只有在列表项渲染进容器后才可以完成定位。

指定高度的无穷列表的滚动性能要稍好于无高度的列表(无高度的列表要多一次列表项的高度查询开销),因此请尽量使用指定高度的无穷列表。 实际上,大多数场景下列表项的高度都是可以确定的,但是对于类似微博首页列表的场景,只能使用不定高度的无穷列表。

为列表项指定高度有两种方式,通过 itemHeight 属性可以为所有列表项指定一个高度,这样所有的列表项是等高的;也可以给 dataSource 中的数组元素添加一个 height 属性,这样可以给每一个元素分别指定一个高度。例子如下:

为所有列表项配置相同的高度:

<List
  dataSource={/* a very long array... */}
  infinite={true}
  itemHeight={44}
  // ...
/>

给每个列表项配置不同的高度:

<List
  dataSource={[
    { text: 'item1', height: 100 },
    { text: 'item2', height: 200 },
    // ...
  ]}
  infinite={true}
  // ...
/>

如果既没有配置 itemHeight ,也没有配置数据源中数据元素的 height 属性, 那么会启动不指定高度模式,列表项的高度会随着列表的滚动计算并保存起来,当所有列表项的高度都被计算之后实际上就切换到了指定高度的模式。

另外一个很重要的属性是 infiniteSize ,它决定了列表将把多少个列表项保留在容器内,默认值为 12 。如果这个值设置的过小,可能会出现保留的列表项内容填不满容器的情况, 如果设置的过大,会将一些本来就不可见的节点渲染出来,造成一些无谓的性能损耗。应该根据实际的业务场景设置这个属性,一般来说保留的列表项的高度大于一个半容器的高度就足够了。

在开启无穷模式以后,列表的滚动过程中会有大量的 dom 更新(尽管我们已经尽力让这个更新操作最小化),这是一个巨大的负担。 实践表明,良好而精简的 dom 结构能够显著降低这个开销,因此请尽量优化列表项的 dom 结构,减少层级和不必要的标签。

图片相关

因为图片是一种异步加载的资源,在图片加载完成后可能会改变内容的高度,因此不指定高度列表中的图片需要给他指定一个高度,否则可能会出现部分内容滑动不上去的问题。主要有两种情况:

  • 如果图片资源路径是通过后端接口传过来的,可以在接口返回的信息中加上该图片原始尺寸。

  • 如果图片是直接写在页面里的,可以在图片标签中通过属性带上图片的原始尺寸信息,例如 <img src="path-to-img" data-origin-height="300" data-origin-width="450" />

拿到图片的原始尺寸后,根据当前图片容器的宽度按比例计算出图片的实际高度并赋值给图片的 height 属性。

图片的懒加载

图片的懒加载(lazyload)是最常见的性能优化手段(List的示例中也应用了懒加载),使用 LazyImage 组件可以很轻易地实现这个功能。 你需要做的是使用 LazyImage 组件取代列表项内部的 <img/> 标签, 并且需要给这个图片指定一个高度,如下:

<List
  // ...
  renderItem={(item,i) => {
    return (
      <a className="img-wrap">
        <List.LazyImage
          src={item.imgUrl}
          defaultImage={null}
          style={{ width: '100%', height: 200 }}
        />
      </a>
    )
  }}
/>

更详细的使用方式请参考 LazyImage 组件的 说明文档

列表项的性能优化和更新

在开启了无穷列表模式的情况下,在滚动过程中会实时更新容器内部的列表项,这会触发大量的 render 过程,虽然 React 的虚拟 dom diff 的开销并不大, 但是对于某些老式手机,如此频繁的触发 dom diff 依然会有不可忽视的性能开销。

为了最大限度地优化滚动的性能,无穷列表的列表项都默认配置了 shouldComponentUpdate 它会根据列表项对应的 item.key 是否发生了变化来决定是否触发 render, 这样可以确保 render 的触发次数达到最小。 你会发现这和使用 Immutable 来优化 render 的原理十分相似。

在默认情况下,如果你想修改列表中某一项的数据,除了设置改变后的属性值之外,你还应该给它设置一个新的 key,否则 ListItem 的 shouldComponentUpdate 的结果仍然为 false ,你期待的 dom 更新也不会发生。

有的时候这会导致用户期待的 render 没有发生,这时候可以通过配置 shouldItemUpdate 属性来覆盖掉默认的 shouldComponentUpdate 返回的结果。例如:

<List
  shouldItemUpdate={(next,now) => {
    // return ...; // true or false
  }}
  // ...
/>

这个函数接收两个参数,第一个参数和第二个参数分别对应着列表项当前的数据和即将接收到的数据。 这个函数返回的布尔值会作为 shouldComponentUpdate 的新结果返回。

这里需要注意一点,如果你没有使用 Immutable 数据结构, 那么 nextnow 此时实际上都会指向同一个对象。所以在这种情况下, 不能简单地通过这两个对象的浅比较来确定是否应该 render

如果你使用了 Immutable ,那么推荐做以下的配置:

<List
  shouldItemUpdate={(next,now) => next !== now }
  // ...
/>

这样当列表项的数据发生变化时,你不必再做修改 key 值的操作而只需要修改数据,改动的列表项将会自动重新 render ,方便许多。

下拉刷新和加载更多

这两个功能继承自 Scroller 组件, 可以查看 Scroller 的文档来了解如何使用,这里仅仅给出一个完整的例子,在这个例子中还应用了 Immutable 数据结构。你可以尝试玩一下右边的 Demo 来看看这段代码究竟做了什么:

import 'babel-polyfill';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Page from '../../../common/page';
import { List, Toast } from '$yo-component';
import { getRandomDataSource } from '../common/baseUtils';
import Immutable from 'immutable';

class ListBase extends Component {
  constructor() {
    super();
    this.state = {
      dataSource: this.getDataSource(25)
    };
  }

  getDataSource(size) {
    return Immutable.fromJS(getRandomDataSource(size));
  }

  refresh() {
    this.setState({ dataSource: this.getDataSource(25) });
  }

  fetch() {
    this.setState({ dataSource: this.state.dataSource.concat(this.getDataSource(15)) });
  }

  render() {
    return (
      <Page title="List Demo" onLeftPress={() => location.href = "./index.html"}>
        <List
          ref="list"
          extraClass="yo-scroller-fullscreen"
          dataSource={this.state.dataSource}
          renderItem={(item, i) => <div>{i + ':' + item.get('text')}</div>}
          infinite={true}
          infiniteSize={20}
          itemHeight={44}
          usePullRefresh={true}
          onRefresh={() => {
            setTimeout(() => {
              this.refresh();
              this.refs.list.stopRefreshing(true);
            }, 500);
          }}
          useLoadMore={true}
          onLoad={() => {
            setTimeout(() => {
              this.fetch();
              this.refs.list.stopLoading(true);
            }, 500);
          }}
          itemExtraClass={(item, i) => {
            return 'item ' + i;
          }}
          onItemTap={(item, i) => {
            Toast.show('item' + i + ' clicked.', 2000);
          }}
        />
      </Page>
    );
  }
}

ReactDOM.render(<ListBase />, document.getElementById('content'));

无穷模式下改变列表项的高度

如上所述,无穷列表的所有位置信息保存在 List 组件内部的一张哈希表中,这个哈希表的键值正是你传入的列表项的 key

因此,如果某一项的高度发生了变化,你需要给它设置一个新的 key ,这样保存高度的哈希表的旧记录就失效了,在列表项重新 render 以后,它的新高度就被用这个新的 key 值保存到哈希表中。 注意:这种改变高度的场景必须通过修改 key 值来实现,即使你已经使用 shouldItemUpdate 改变了原有的 shouldComponentUpdate

右侧的 Demo 展示了一个需要展开完整文本内容的场景,这正是一个典型的需要改变列表项高度的需求,它的代码如下:

class ModifyHeightDemo extends Component {
  static guid = -1;

  constructor() {
    super();
    this.state = {
      dataSource: Immutable.fromJS(dataSource.map(item => {
        const len = item.comment.trim().length;
        return {
          ...item,
          showMoreFlag: false,
          key: ++ModifyHeightDemo.guid,
          shortComment: len > 150 ? item.comment.substr(0, 150) + '...' : item.comment,
          commentHasMore: len > 150 ? 1 : 0
        };
      }))
    };
  }

  // 展开/收起内容,注意这里key值发生的变化
  toggle(item) {
    this.setState({
      dataSource: this.state.dataSource.map(it => {
        if (it === item) {
          return it
            .set('key', ++ModifyHeightDemo.guid)
            .set('showMoreFlag', !it.get('showMoreFlag'));
        }
        return it;
      })
    });
  }

  render() {
    return (
      <Page title="Modify Height" onLeftPress={() => location.href = "./index.html"}>
        <List
          extraClass="yo-scroller-fullscreen m-sight-comment-list"
          dataSource={this.state.dataSource}
          renderItem={(item) => <DemoItem data={item} toggle={() => this.toggle(item)}/>}
          infinite={true}
          infiniteSize={5}
        />
      </Page>
    );
  }
}

Static Section

在业务需求中经常会遇到界面的一部分是列表形式,一部分是静态内容的情况。 这种场景可以借助 staticSection 属性实现,给这个属性传入的 JSX 将会被渲染到所有列表项之上,例如:

<List
  staticSection={<div>static section...</div>}
  // ...
/>

下面的代码是一个更复杂的例子,这个例子实现的是类似去哪儿旅行客户端首页的效果,上部区域是静态内容,下半部分是一个 Infinite 的列表, 还实现了一个横向的可滚动 Tab,你可以在右边的 Demo 中查看效果:

class Demo extends Component {
  constructor() {
    super();
    this.state = {
      dataSource: getRandomDataSource(25),
      x: 0
    };
  }

  getContent() {
    return [1, 2, 3, 4, 5].map((item) => {
        return <div className="item" style={{ background: 'green' }} key={item}>{item}</div>;
    });
  }

  getGroup(i) {
    return (
      <div key={i} className="demo-group">
        <Scroller.Sticky>
          <div style={{ height: 50, lineHeight: 50 + 'px' }} className="sticky-title">
            <span>{'Sticky Header ' + i}</span>
            <Touchable touchClass='touchable-opacity' onTap={() => {
              Toast.show('sticky header ' + i);
            }}>
              <span className="touchable-right" style={{ float: 'right' }}>tap!</span>
            </Touchable>
          </div>
        </Scroller.Sticky>
        {this.getContent()}
      </div>
    );
  }

  refresh() {
    this.setState({ dataSource: getRandomDataSource(25) });
  }

  fetch() {
    this.setState({ dataSource: this.state.dataSource.concat(getRandomDataSource(15)) });
  }

  render() {
    return (
      <Page title="List: Static Section" onLeftPress={() => location.href = "./index.html"}>
          <List
            directionLockThreshold={3 /* 这个属性用来改变竖向滚动的阈值,因为这个例子中存在横向滚动容器,设置一个小的阈值可以解决方向冲突问题 */}
            staticSection={
              <div className="demo-static-header">
                {[0, 1, 2].map(num => this.getGroup(num))}
                <Scroller.Sticky>
                  <div>
                    <div style={{ height: 50, lineHeight: 50 + 'px' }} className="sticky-title">
                      <span>{'Sticky Header For List'}</span>
                    </div>
                    <Scroller
                      style={{ height: 50, width: '100%', background: 'white' }}
                      scrollX={true}
                      scrollY={false}
                      bounce={false}
                      contentOffset={{ x: this.state.x || 0, y: 0 }}
                      onScrollEnd={(evt) => {
                          const x = evt.contentOffset.x;
                          this.setState({ x })
                      }}
                    >
                      <div style={{ height: '100%', width: 600 }}>
                        {[1, 2, 3, 4, 5, 6, 7].map(num => (
                          <span key={num} className="scroller-item">{num}</span>
                        ))}
                      </div>
                    </Scroller>
                  </div>
                </Scroller.Sticky>
              </div>
            }
            ref="list"
            extraClass="yo-scroller-fullscreen"
            dataSource={this.state.dataSource}
            renderItem={(item, i) => <div>{i + ':' + item.text}</div>}
            infinite={true}
            infiniteSize={20}
            itemHeight={44}
            useLoadMore={true}
            onLoad={() => {
              setTimeout(() => {
                this.fetch();
                this.refs.list.stopLoading(true);
              }, 500);
            }}
            onItemTap={(item, i) => {
              Toast.show('item' + i + ' clicked.', 2000);
            }}
          />
      </Page>
    );
  }
}
属性

dataSource { Array/Immutable List } #

组件的数据源,数组或者Immutable List类型,内部元素必须是对象或者Immutable Map。 如果需要给无穷列表的项定高度,可以给元素添加height属性(数字类型), 也可以通过itemHeight属性统一设置列表项的高度(见itemHeight属性的描述), 如果列表元素有text属性且没有传入renderItem,会直接以text的值作为listitem的内容渲染。

默认值: none

renderItem { Function } #

定制如何根据列表项数据对象渲染列表项的函数,接收参数item(数据对象)和index(在数据源中的index),返回一个JSX。 如果传入字符串,则会应用于所有列表项。

例子:renderItem={(item)=><p>{item.someAttr}</p>}

默认值: (item)=>item.text

uniqueKeyName { String } 3.1.3 #

dataSource 数组项的唯一标识的键值,默认为 key。

例子:renderItem={(item)=><p>{item.someAttr}</p>}

默认值: 'key'

onItemTap { Function } #

点击列表项时的事件回调,接收三个参数item(列表项对应的数据对象),index(列表项在数据源中的index)以及target(当前事件的event.target),

List实现了独特的手势系统以达到iOS列表的手势效果,任何情况下都应该使用这个属性为ListItem绑定事件,而不是给ListItem中的节点绑定onTouchTap事件。

默认值: null

方法参数:

参数名 类型 描述 支持版本
item Object 列表项对应的数据对象
index Number 列表项在数据源中的index
target DOMElement 当前tap事件的target

infinite { Bool } #

是否使用无穷列表模式。

开启无穷列表模式后,列表中只会保留infiniteSize个节点,并随着滚动复用这些节点,以此来优化大列表的性能,但是滚动过程中会有性能损耗。 如果你的列表项数量不大(比如只有几十个),请不要开启无穷模式。

默认值: false

infiniteSize { Number } #

无穷列表模式下,保留在列表容器中列表项的个数(参见无穷列表模式的说明).

注意:这个值应该随着列表容器的高度和列表项高度选取一个合适的值,否则可能出现列表容器底部出现空白的情况。 如果这个值设置的过大,会降低列表的滚动性能,因此请根据实际情况(List容器的高度和列表项的高度)灵活配置。

默认值: 12

itemHeight { Number } #

无穷列表中列表项的高度。

如果数据源中的对象没有height属性,也没有设置itemHeight,则会使用不定高的无穷列表模式。 在不定高模式下,每个项的高度会在渲染进容器以后确定,因此比定高模式多一次offsetHeight的查询,性能会差一些。

默认值: null

offsetY { Number } #

组件的初始位置的Y坐标。

默认值: 0

contentInset { Number } 3.0.13 #

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

默认值: {bottom:0}

itemExtraClass { String/Function } #

给列表项容器元素添加的class

默认值: "item item-wrap"

方法参数:

参数名 类型 描述 支持版本
item Object 列表项对应的数据对象
index Number 列表项在数据源中的index 可以接受字符串形式。例如"custom-list-item"(会自动应用在所有列表项容器上) 或者一个函数,这个函数接受参数item(列表项对应的dataSource中的数据对象),index(数据源index) 例:(item)=>{return item.customClassName}/'custom-item-classname'。

itemTouchClass { String/Function } #

列表项被点击时的className,可以接收字符串或者函数,使用方式与itemExtraClass一致。

默认值: item-touch

方法参数:

参数名 类型 描述 支持版本
item Object 列表项对应的数据对象
index Number 列表项在数据源中的index

onScroll { Function } #

绑定给list内部scroller的onScroll回调,在列表滚动时触发。

默认值: null

方法参数:

参数名 类型 描述 支持版本
offsetY Number 当前 Scroller 的 y 轴偏移量
direction Enum {'up','down'} 列表滚动的方向,向上('up')或者向下('down')

onScrollEnd { Function } 3.1.4 #

滚动结束之后的回调

默认值: null

方法参数:

参数名 类型 描述 支持版本
offsetY Number 当前 Scroller 的 y 轴偏移量

style { Object } 3.0.2 #

给List容器节点绑定的额外样式。

默认值: null

onInfiniteAppend { Function } #

无穷列表中列表项update时触发的事件回调,接收参数visibleList(数组),为目前渲染在列表容器中的数据项。

默认值: null

方法参数:

参数名 类型 描述 支持版本
visibleList Array 当前渲染在列表容器中的数据项数组

staticSection { Element } 3.0.3 #

在所有列表项之上渲染的一块静态区域,在开启Infinite模式时,这块区域不会参与列表项的回收复用。

默认值: null

extraClass { String } #

组件容器元素的额外className。

默认值: null

containerExtraClass { String } #

列表容器元素额外的className(对应ul.yo-list节点)。

默认值: null

usePullRefresh { Bool } #

是否使用下拉刷新,见Scroller同名属性。

默认值: false

pullRefreshHeight { Number } #

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

默认值: 40

renderPullRefresh { Function } #

() => JSX

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

返回值: JSX 用来渲染

onRefresh { Function } #

下拉刷新触发的事件回调。

默认值: null

方法参数:

参数名 类型 描述 支持版本
dataSource Array 当前的数据源

useLoadMore { Bool } #

是否开启加载更多,见Scroller同名属性。

默认值: false

loadMoreHeight { Number } #

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

默认值: 40

renderLoadMore { Function } #

() => JSX

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

返回值: JSX 用来渲染

onLoad { Function } #

加载更多时触发的事件回调。

默认值: null

方法参数:

参数名 类型 描述 支持版本
dataSource Array 当前数据源

shouldItemUpdate { Function } #

绑定给列表项组件的shouldComponentUpdate,可以避免额外的render,用于提升列表的滚动性能。

实验表明,组件的render开销对于某些老式手机(例如三星Note2)是不能忽视的,因此list默认为所有的列表项组件配置了shouldComponentUpdate,会根据 item的_guid属性(List组件自己做的,不需要使用者传入)做比较决定是否需要render,这样可以最小化render的次数。有些情况下,这种比较方式会阻止使用者期待触发的render,导致组件更新行为违反了使用者的意愿,这时候需要通过设置shouldItemUpdate属性改变默认的shouldComponentUpdate的返回值

shouldItemUpdate能够接受两个参数,next(ListItem组件的下一个props中的item属性), now(ListItem当前的props的item属性)。它必须返回一个布尔值,false则会跳过render,true会继续执行render(与shouldComponentUpdate返回值的含义相同)。

默认值: null

方法参数:

参数名 类型 描述 支持版本
next Object 即将传给列表项组件的item对象
now Object 当前列表项组件对应的item对象

disabled { Bool } #

是否禁止滚动,参见Scroller的同名属性。

默认值: false

stickyOffset { Number } 3.0.6 #

给staticSection内部吸顶容器设置的y轴偏移。

默认值: 0

directionLockThreshold { Number } 3.0.2 #

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

默认值: 5

deceleration { Number } 3.0.6 #

滚动视图开始惯性滚动时减速的加速度,默认为0.001。

scrollWithoutTouchStart { Bool } 3.0.2 #

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

默认值: false

scrollIntoView { String } 3.1.7 #

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

默认值: ''

方法

refresh #

刷新列表,应该在列表容器高度发生改变时调用

resetLoadStatus 3.0.7 #

重置加载更多功能。

方法参数:

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

stopRefreshing #

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

方法参数:

参数名 类型 描述 必选 支持版本
success Bool 下拉刷新是否成功,默认为 false。
config Object 停止刷新的动画配置。
config.duration number 回到顶部的动画时间,默认是 300ms。
callback Function 回到顶部的动画执行完毕的回调。

stopLoading #

中止加载更多过程,使用方式和场景与stopRefreshing一致。

方法参数:

参数名 类型 描述 必选 支持版本
successed Bool 加载更多是否成功,默认为false

startRefreshing #

模拟下拉刷新,调用这个方法后,会立刻停止当前的滚动并回到列表顶部,然后开始下拉刷新过程。

注意:你仍然需要手动调用stopRefreshing方法

scrollTo #

让List滚动到某个位置

方法参数:

参数名 类型 描述 必选 支持版本
y Number 要滚动到的目标y坐标
time Number 动画时间,默认为0。 (在开启了无穷模式的情况下,为了提高滚动的性能,不管time传入什么值都会被重设为0.因为快速滚过很长的距离在无穷模式下会带来巨大的性能损耗)

stopAnimate #

立刻停止滚动。