For AI agents: the complete documentation index is available at /next/zh/llms.txt, the full documentation bundle is available at /next/zh/llms-full.txt, and this page is available as Markdown at /next/zh/api/elements/built-in/list.md.
Lynx
  • 简体中文
  • <list>

    <list> 组件是一个高性能的可滚动容器,通过元素回收和懒加载机制优化性能和内存使用。它支持横向和纵向滚动,可实现单列、网格和瀑布流布局,非常适合无限滚动的信息流等应用场景。

    使用指南

    单列布局

    1. 设置宽高<list> 的宽高代表了其可视区域的大小,因此需要是确定的值,不能由内部内容撑开,只有在可视区域内可见的子节点才会被渲染。

    2. 设置滚动方向与布局形式:设置属性 scroll-orientation 指定布局与滚动方向,设置 list-typespan-count 指定布局形式。

    3. 配置子节点:使用标签 <list-item> 作为 <list> 直接子节点,并且给 <list-item> 设置 item-keykey,并且需要保持一致。

    多列布局

    1. 设置布局方式与列数: 设置布局形式 list-typeflow (网格布局) 或者 waterfall (瀑布流布局),并设置 span-count >= 2。

    2. 多列布局下实现独占一行的子节点: 为 <list-item/> 设置 full-span 属性,可以使其在布局中独占一行或者一列。

    网格布局案例:

    瀑布流布局示例

    List 相关 CSS 属性

    Note

    List 相关 CSS 属性是专门为 <list> 组件设计的,例如 list-main-axis-gaplist-cross-axis-gap,可以对 <list> 内元素的布局和间距进行精细控制。需要注意的是,这些属性只在 <list> 上生效,在其他任何组件上都将被忽略。

    list-main-axis-gap

    // DefaultValue: null
    list-main-axis-gap?: ${number}px | ${number}rpx
    
    <list
      style={{listMainAxisGap:'10px'}}
    />

    指定了在主轴方向上,<list> 子节点的间距,需要写在 style 中。

    list-cross-axis-gap

    // DefaultValue: null
    list-cross-axis-gap?: ${number}px | ${number}rpx
    
    <list
      style={{listCrossAxisGap:'10px'}}
    />

    指定了在副轴方向上,<list> 子节点的间距,需要写在 style 中。

    属性

    list-type Required

    list-type: 'single' | 'flow' | 'waterfall'

    控制 <list> 组件的布局类型,需要与 span-count 配合使用。

    说明
    single单列/单行布局
    flow多列/多行网格布局。网格布局会充分体现其归整性,左右两列中,相邻位置子节点的 top 是一致的,因此使用场景通常为大小一致的子节点。子节点宽度由 <list> 的宽度和 span-count 决定
    waterfall多列/多行瀑布流布局。内容是连续填充的,子节点元件是从上到下填充到最短的列,实现视觉上的连续和动态性,因此使用场景通常为大小不一致的子节点。子节点宽度由 <list> 的宽度和 span-count 决定

    你可以通过查看多列布局指南 中的真实案例更清晰地看出 flowwaterfall 的布局差异。

    span-count Required

    span-count: number

    设置 <list> 组件的布局列数或者行数。

    scroll-orientation Required

    // DefaultValue: "vertical"
    scroll-orientation?: 'vertical''horizontal'

    设置 <list> 组件的滚动方向与布局方向。

    item-key Required

    // DefaultValue: null
    item-key: string
    
    <list-item item-key="item"/>

    item-key<list-item> 上必须传入的属性。

    Note

    开发者需要为每一个 <list> 子节点设置唯一的 item-key,其会被用来帮助 <list> 识别哪些 <list> 子节点已更改、添加或删除。因此开发者需要保证正确设置 item-key,如设置有误,将会导致错乱、闪动问题。

    key Required

    // DefaultValue: null
    key: string
    
    <list-item
      item-key="item-0"
      key="item-0"
    />

    使用 key 属性来帮助框架识别哪些元件已更改、添加或删除。

    Note

    在 list 场景下,keyitem-key 保持一致。

    enable-scroll

    // DefaultValue: true
    enable-scroll?: boolean

    是否允许 <list> 组件滚动。

    enable-nested-scroll

    // DefaultValue: true
    enable-nested-scroll?: boolean

    是否允许 <list> 与其他滚动容器实现嵌套滚动,开启后先滚动内层容器,再滚动外层容器。

    sticky

    // DefaultValue: false
    sticky?: boolean

    声明在 <list> 组件上,控制 <list> 组件整体是否允许吸顶或者吸底。

    sticky-offset

    // DefaultValue: 0
    sticky-offset?: number

    吸顶或者吸底位置距离 <list> 顶部或者底部的偏移,单位为 px

    sticky-top

    // DefaultValue: false
    sticky-top?: boolean

    声明在子节点 <list-item> 上,控制该节点是否会吸顶。

    sticky-bottom

    // DefaultValue: false
    sticky-bottom?: boolean

    声明在子节点 <list-item> 上,控制该节点是否会吸底。

    recyclable

    // DefaultValue: true
    recyclable?: boolean
    "dependencies": {
      "@lynx-js/react": "^0.112.2"
    }

    声明在子节点 <list-item> 上,控制该节点是否会被回收,如果 recyclable 设置为 false,则 <list-item> 被滑出 <list> 可视区域后不会被回收。

    bounces

    // DefaultValue: true
    bounces?: boolean

    开启边缘回弹效果。

    initial-scroll-index

    // DefaultValue: 0
    initial-scroll-index?: number

    指定 <list> 在渲染后自动定位到的节点位置,仅首次生效。

    need-visible-item-info

    // DefaultValue: false
    need-visible-item-info?: boolean

    控制滚动事件回调参数中是否包含当前正在渲染节点的位置信息,这里滚动事件包含:scrollscrolltoupperscrolltolower

    滚动事件回调参数格式:

    interface ListScrollInfo {
      // 距上次滚动的横向滚动偏移量,单位 px
      deltaX: number;
      // 距上次滚动的纵向滚动偏移量,单位 px
      deltaY: number;
      // 当前横向滚动偏移量,单位 px
      scrollLeft: number;
      // 当前纵向滚动偏移量,单位 px
      scrollTop: number;
      // 当前内容区域宽度,单位 px
      scrollWidth: number;
      // 当前内容区域高度,单位 px
      scrollHeight: number;
      // `<list>`宽度,单位 px
      listWidth: number;
      // `<list>`高度,单位 px
      listHeight: number;
      // 滚动事件源
      eventSource: ListEventSource;
      // 当前正在渲染节点的位置信息
      attachedCells: [
        {
          id: number; // 节点 id
          itemKey: string; // 节点 item-key
          index: number; // 节点在 list 中的 index
          left: number; // 节点左边界相对于 list 的位置,单位 px
          top: number; // 节点上边界相对于 list 的位置,单位 px
          right: number; // 节点右边界相对于 list 的位置,单位 px
          bottom: number; // 节点下边界相对于 list 的位置,单位 px
        },
      ];
    }

    upper-threshold-item-count

    // DefaultValue: 0
    upper-threshold-item-count?: number

    <list> 顶部剩余可展示的子节点个数首次小于 upper-threshold-item-count 时,触发一次 scrolltoupper 事件。

    lower-threshold-item-count

    // DefaultValue: 0
    lower-threshold-item-count?: number

    <list> 底部剩余可展示的子节点个数首次小于 lower-threshold-item-count 时,触发一次 scrolltolower 事件。

    scroll-event-throttle

    // DefaultValue: 200
    scroll-event-throttle?: number

    用于设置 <list> 回调 scroll 事件的时间间隔,单位为毫秒(ms)。其默认 200 ms 回调一次滚动事件。

    Note

    engineVersion 版本小于

    3.4,该属性无法生效,因此不会拦截 scroll 事件回调。当 engineVersion 版本大于等于
    3.4
    ,如果不设置改属性,则使用默认值 200 ms。

    item-snap

    // defaultValue: undefined
    'item-snap'?: ListItemSnapAlignment;
    
    interface ListItemSnapAlignment {
      factor: number;
      offset: number;
    }

    控制 <list> 实现分页滚动的效果。

    分页参数

    • factor: 分页定位锚定位置的参数,取值范围 [0, 1]
      • 取值为 0 代表分页滚动的 <list> 子节点和 <list> 顶部对齐
      • 取值为 1 代表分页滚动的 <list> 子节点和 <list> 底部对齐
    • offset: 额外增加偏移参数,在 factor 的基础之上再进一步添加偏移量
    Note

    engineVersion 版本小于 3.2 时,列表滚动速率会存在不一致问题。

    update-animation

    update-animation?: "default" | "none"

    该属性用于控制在数据源更新时,列表是否运行动画。当前支持插入、删除和更新动画。


    delete

    update

    insert
    Note

    当前 update-animation 只能在 list-typesingleflow 时生效。

    need-layout-complete-info

    控制 layoutcomplete 事件中是否包含本次 layout 前后的节点排版信息,触发本次排版的 <list> Diff 信息,以及当前 <list> 的滚动状态信息。

    export interface LayoutCompleteEvent extends BaseEvent<'layoutcomplete', {}> {
      detail: {
        'layout-id': number;
        // 开启 need-layout-complete-info
        scrollInfo: ListScrollInfo;
        // 开启 need-layout-complete-info
        diffResult?: {
          insertions: number[];
          move_from: number[];
          move_to: number[];
          removals: number[];
          update_from: number[];
          update_to: number[];
        };
        // 开启 need-layout-complete-info
        visibleCellsAfterUpdate?: ListItemInfo[];
        // 开启 need-layout-complete-info
        visibleCellsBeforeUpdate?: ListItemInfo[];
      };
    }

    layout-id

    // defaultValue: -1
    layout-id?: number

    用于标记本次数据源更新的唯一标识,会在 layoutcomplete 事件回调中返回这个 id。

    preload-buffer-count

    // DefaultValue: 0
    preload-buffer-count?: number

    该属性可以控制 <list> 提前加载 <list> 外节点的个数。

    Note
    • preload-buffer-count 的值越大,可以提前加载的屏外节点越多,但是也会增加 <list> 内存占用。

    • preload-buffer-count 的取值建议为占满 <list> 一屏的节点个数。

    • list-type='single'/'flow' 时生效。

    scroll-bar-enable

    // DefaultValue: true
    scroll-bar-enable?: boolean

    是否显示 <list> 组件滚动条

    harmony-scroll-edge-effect

    // DefaultValue: true
    harmony-scroll-edge-effect: boolean

    在 Harmony 上,当 contentSize 小于自身容器大小,设置是否开启滑动效果。

    reuse-identifier

    // DefaultValue: null
    reuse-identifier: string
    
    <list>
      <list-item
        reuse-identifier="type1"
      >
      <list-item
        reuse-identifier="type2"
      >
    </list>

    设置 <list-item> 复用 id,<list> 组件在渲染子节点时,会根据 <list-item>reuse-identifier 属性值对 <list-item> 进行复用,只有设置了相同的 reuse-identifier 属性值的 <list-item> 才会被复用。

    默认情况下,开发者不提供需要 reuse-identifier,而是由框架在编译阶段确定,比如:当 <list-item> 处于循环内(例如 Array.prototype.map 等)时,由于它们在编译阶段的形态和位置相同,我们会为它们生成相同的 reuse-identifier,我们会认为这一组 <list-item> 可以互相复用。

    Note

    使用场景:结构差异非常大的 <list-item> 在复用时性能比较差,因此建议为它们设置不同的 reuse-identifier,以避免它们之前被相互复用。

    full-span

    // DefaultValue: false
    full-span?: boolean
    
    <list>
      <list-item full-span={true}/>
    </list>

    属性 full-span 用于标识 <list-item> 独占一行或者一列。

    estimated-main-axis-size-px

    // DefaultValue: -1
    estimated-main-axis-size-px?: number
    
    <list-item
      estimated-main-axis-size-px={100}
    />

    用于指定 <list-item> 还未渲染完成时,在主轴方向上的占位大小,单位为 px,如果不设置,默认值为 <list> 在主轴方向上的大小。

    Note

    强烈建议开发者设置与子节点真实大小相近的 estimated-main-axis-size-px

    experimental-recycle-sticky-item

    // DefaultValue: true
    experimental-recycle-sticky-item?: boolean

    <list> 中存在多个吸顶或者吸底的节点时,当吸顶或吸底的节点被其他吸顶或吸底的节点推出 <list> 区域后回收该节点,以解决吸顶或者吸底的节点过多导致的内存开销问题。此优化在 engineVersion 版本大于等于

    3.4 时 默认开启。


    吸顶的节点不回收,<list-item> 数量会不断增长

    吸顶的节点回收,<list-item> 会被复用,数量不会增长

    事件

    前端可以在元件上绑定相应事件回调来监听元件的运行时行为,使用方法如下。

    scroll

    bindscroll?: EventHandler<ListScrollEvent>;
    
    interface ListScrollEvent {
      // 距上次滚动的横向滚动偏移量,单位 px
      deltaX: number;
      // 距上次滚动的纵向滚动偏移量,单位 px
      deltaY: number;
      // 当前横向滚动偏移量,单位 px
      scrollLeft: number;
      // 当前纵向滚动偏移量,单位 px
      scrollTop: number;
      // 当前内容区域宽度,单位 px
      scrollWidth: number;
      // 当前内容区域高度,单位 px
      scrollHeight: number;
      // `<list>`宽度,单位 px
      listWidth: number;
      // `<list>`高度,单位 px
      listHeight: number;
      // 滚动事件源
      eventSource: ListEventSource;
      // 当前正在渲染节点的位置信息
      attachedCells: [
        {
          "id": number,        // 节点 id
          "itemKey": string,   // 节点 item-key
          "index": number,     // 节点在 list 中的 index
          "left": number,      // 节点左边界相对于 list 的位置,单位 px
          "top": number,       // 节点上边界相对于 list 的位置,单位 px
          "right": number,     // 节点右边界相对于 list 的位置,单位 px
          "bottom": number,    // 节点下边界相对于 list 的位置,单位 px
        },
      ];
    }
    
    enum ListEventSource {
      DIFF = 0,
      LAYOUT = 1,
      SCROLL = 2,
    }

    <list> 滚动事件。

    Note

    scrolltoupper

    bindscrolltoupper?: EventHandler<ListScrollEvent>;

    滚动到 <list> 顶部时触发的回调。该回调触发的位置可以由 upper-threshold-item-count 控制。

    scrolltolower

    bindscrolltolower?: EventHandler<ListScrollEvent>;

    滚动到 <list> 底部时触发的回调。该回调触发的位置可以由 lower-threshold-item-count 控制。

    scrollstatechange

    bindscrollstatechange?: EventHandler<ListScrollStateChangeEvent>;
    
    interface ScrollStateChangeEvent extends CustomEvent {
      detail: {
        // 本次滑动的滑动状态,取值说明
        //   1 - 静止
        //   2 - 拖拽
        //   3 - 惯性滚动
        //   4 - 动画滚动
        state: number;
      };
    }

    <list> 滚动状态变化时触发的回调。事件参数的字段 detail 里的 state 分别取值: 1234,分别表示 <list> 滚动状态为:静止、拖拽、惯性滚动、动画滚动。

    layoutcomplete

    bindlayoutcomplete?: EventHandler<ListLayoutFinishEvent>;
    
    interface LayoutCompleteEvent extends BaseEvent<'layoutcomplete', {}> {
      detail: {
        'layout-id': number;
        // 需要开启 need-layout-complete-info
        scrollInfo: ListScrollInfo;
        // 需要开启 need-layout-complete-info
        diffResult?: {
          insertions: number[];
          move_from: number[];
          move_to: number[];
          removals: number[];
          update_from: number[];
          update_to: number[];
        };
        // 需要开启 need-layout-complete-info
        visibleCellsAfterUpdate?: ListItemInfo[];
        // 需要开启 need-layout-complete-info
        visibleCellsBeforeUpdate?: ListItemInfo[];
      };
    }
    
    interface ListItemInfo {
      // 子节点高度
      height: number;
      // 子节点宽度
      width: number;
      // 子节点 itemKey
      itemKey: string;
      // 子节点是否处于渲染状态
      isBinding: boolean;
      // 子节点相对于全部滚动区域的 x 坐标位置
      originX: number;
      // 子节点相对于全部滚动区域的 y 坐标位置
      originY: number;
      // 子节点是否存被更新
      updated: boolean;
    }

    <list> 布局完成后触发回调。

    snap

    bindsnap?: EventHandler<ListSnapEvent>;
    
    interface ListSnapEvent extends common.BaseEvent<'snap', {}> {
      detail: {
        // 将会分页滚动到的节点索引
        position: number;
        // 当前横向滚动偏移量,单位 px
        currentScrollLeft: number;
        // 当前纵向滚动偏移量,单位 px
        currentScrollTop: number;
        // 分页滚动的目标横向滚动偏移量,单位 px
        targetScrollLeft: number;
        // 分页滚动的目标纵向滚动偏移量,单位 px
        targetScrollTop: number;
      };
    };

    即将发生分页滚动时的回调。

    方法

    scrollToPosition

    this.createSelectorQuery()
      .select('#id_of_list')
      .invoke({
        method: 'scrollToPosition',
        params: {
          position: 10,
          offset: 100,
          alignTo: 'top',
          itemKey: `${itemKey}`,
          smooth: true,
        },
        success: function (res) {},
        fail: function (res) {},
      })
      .exec();

    <list> 组件滚动到指定的位置,参数说明:

    参数名类型默认值必填简介
    positionnumber指定要滚动到的节点的 index, 取值范围为[0, 数据源个数)
    offsetnumber在应用 alignTo 对齐后,继续滚动 offset 长度
    alignTostringnull滚动后目标节点在视图中的位置.

    "bottom": 滑动至该节点在 <list> 中完全可见,且该节点的底部和 <list> 的底部对齐

    "top": 滑动至该节点在 <list> 中完全可见,且该节点的顶部和 <list> 的顶部对齐

    "middle": 滑动至该节点在 <list> 中完全可见,且该节点在 <list> 中垂直居中
    itemKeystringnull指定要滚动到的节点的 item-key,如果同时设置了 item-keyposition 参数,则优先滚动到 item-key 对应的节点
    smoothbooleanfalse滑动过程中是否有动画

    autoScroll

    this.createSelectorQuery()
      .select('#id_of_list')
      .invoke({
        method: 'autoScroll',
        params: {
          rate: '60px', //  每一秒滚动的间距,支持正负。间距支持单位"px/rpx/ppx" default->null (iOS 取值必须大于 1/screen.scale px)
          start: true, //  开始/暂停自动滚动 default->false
          autoStop: true, // 滑到底部是否自动停止 default->true
        },
        success: function (res) {},
        fail: function (res) {},
      })
      .exec();

    触发 <list> 自动滚动,参数说明:

    参数名类型默认值必填简介
    ratestringnull每一秒滚动的间距,支持正负,可设置单位:px/rpx/ppx
    startboolfalse开始或者暂停自动滚动,true: 开始自动滚动,false: 暂停自动滚动
    autoStopbooltrue滑到底部是否自动停止

    getVisibleCells

    lynx
      .createSelectorQuery()
      .select('#id_of_list')
      .invoke({
        method: 'getVisibleCells',
        success(res) {
          console.log('succ ');
        },
        fail(res) {
          console.log('err ');
        },
      })
      .exec();

    获取当前展示的所有 <list> 子节点的信息。返回信息如下:

    attachedCells: [
      {
        id: number, // 节点 id
        itemKey: string, // 节点 item-key
        index: number, // 节点在 list 中的 index
        left: number, // 节点左边界相对于 list 的位置,单位 px
        top: number, // 节点上边界相对于 list 的位置,单位 px
        right: number, // 节点右边界相对于 list 的位置,单位 px
        bottom: number, // 节点下边界相对于 list 的位置,单位 px
      },
    ];

    scrollBy

    lynx
      .createSelectorQuery()
      .select('#id_of_list')
      .invoke({
        method: 'scrollBy',
        params: {
          offset: 100,
        },
        success(res) {
          console.log('succ ');
        },
        fail(res) {
          console.log('err ');
        },
      })
      .exec();

    在现有偏移量的基础上继续滚动 offset 指定的距离,单位 px,返回的信息如下:

    {
      "consumedX" : number,  // 水平方向滚动的距离,单位 px
      "consumedY" : number,  // 竖直方向滚动的距离,单位 px
      "unconsumedX" : number,  // 水平方向未滚动的距离,单位 px
      "unconsumedY" : number,  // 竖直方向未滚动的距离,单位 px
    }

    更多功能

    实现节点吸顶或者吸底

    <list> 组件中,可以通过设置 <list-item>sticky-topsticky-bottom 属性来实现节点吸顶或者吸底效果。

    确保 <list> 组件的 sticky 属性设置为 true,以允许子节点吸顶,并且可以设置 sticky-offset 来确定吸顶或者吸底位置距离 <list> 顶部或者底部的偏移。

    <list
      className="list-container"
      sticky={true}
      sticky-offset={50}
      list-type="single"
      span-count={1}
      scroll-orientation="vertical"
    >

    <list-item> 上设置 sticky-topsticky-bottom 属性,使该节点在滚动时吸顶或者吸底。由于吸顶或者吸底节点一定是独占一行的节点,因此也需要给该节点设置 full-span 属性。

    <list-item
      className="sticky-top-item"
      full-span={true}
      sticky-top={true}
      item-key={`list-item-${index}`}
      key={`list-item-${index}`}
    />

    实现滚动到底部加载更多数据

    <list> 组件中,你可以实现无限滚动加载的功能。这需要两个步骤:

    1. 设置 lower-threshold-item-count 属性来控制触发时机。当列表滚动到距离底部还剩指定数量的 item 时,就会触发加载。

    2. 监听 scrolltolower 事件。当触发条件满足时,该事件会被调用,你可以在回调函数中请求新数据并添加到列表中。

    利用 item-snap 实现分页滚动

    通过设置 factor 来确定分页滚动定位的参数,取值范围 [0, 1]. 以竖直方向为例,0 代表 <list-item><list> 顶部对齐,1 代表 <list-item><list> 底部对齐,还可以通过设置 offset,从而在 factor 的基础上添加滚动偏移量。

    竖直方向:

    水平方向:

    使用 z-index

    实现 <list-item> 不回收

    通过给 <list-item> 设置 recyclablefalse 来实现该节点不回收。在这个例子中,我们给第一个 <list-item> 中添加了一个溢出且带背景色的 <view> 节点,当这个 <list-item> 被滑动出屏幕后,我们依然可以看到这个带背景色的 <view> 在屏幕上。

    兼容性

    <list>

    LCD tables only load in the browser

    <list-item>

    LCD tables only load in the browser

    除非另有说明,本项目采用知识共享署名 4.0 国际许可协议进行许可,代码示例采用 Apache License 2.0 许可协议进行许可。