实现一个高性能长列表

在 Web 中,实现一个高性能的长列表容器是一件令人困扰的事情。Kraken 内置了 display: sliver 的扩展布局方式,方便前端开发者实现一个带有回收特性的高性能列表容器。

简单的例子

  1. const container = document.createElement('div');
  2. // 修改 display 为 sliver.
  3. container.style.display = 'sliver';
  4. // 必须指定渲染容器节点滚动方向的尺寸(height).
  5. container.style.height = '100vh';
  6. // 创建 100 个子节点.
  7. for (let i = 0; i < 100; i++) {
  8. const ele = document.createElement('div');
  9. ele.style.background = i % 2 ? '#fff' : '#e6e6e6';
  10. // Sliver 元素默认滚动方向为垂直方向
  11. // 它的子元素在水平方向上的尺寸(width)会被自动撑满.
  12. ele.style.padding = '35rpx 60rpx';
  13. ele.appendChild(document.createTextNode(`第 ${i + 1} 个元素`));
  14. // 模拟内部元素高度不定场景
  15. if (i % 3 === 0) {
  16. const img = new Image();
  17. img.src =
  18. 'https://gw.alicdn.com/tfs/TB1.A6OslBh1e4jSZFhXXcC9VXa-229-255.png';
  19. img.width = '50px';
  20. ele.appendChild(img);
  21. }
  22. container.appendChild(ele);
  23. }
  24. document.body.appendChild(container);

渲染效果

实现一个高性能长列表 - 图1
请选择以下任意一种方式预览:
1. 安装 Kraken CLI,然后复制以下命令到命令行中运行:
2. 在 Android 手机上先下载 Play Kraken App,然后打开 App 扫描下方二维码预览:
实现一个高性能长列表 - 图2

这样一个简单的 Sliver 滚动列表就可以工作了,当你向下滚动的时候,Kraken 会动态生成对应的 RenderObject 并同时释放已经移出可视区域(Viewport)的节点对应的 RenderObject。

渐进式支持

目前 display: sliver 仅在 Kraken 中得到支持,如果你希望将一份前端代码复用到 Kraken、浏览器等多端,还需要做一些兼容,以 React / Rax 组件封装为例:

以下代码仅作参考。

  1. // ScrollView 组件的部分实现
  2. const isKraken = typeof kraken !== 'undefined';
  3. // ...
  4. const defaultStyle = {
  5. // ...
  6. };
  7. export default function ScrollView(props) {
  8. const { children, style } = props;
  9. const styleToRender = {
  10. display: isKraken ? 'sliver' : 'block',
  11. ...defaultStyle,
  12. ...style,
  13. };
  14. return (
  15. <div {...props} style={style}>
  16. {props.children}
  17. </div>
  18. );
  19. }

与流式布局的差异与常见问题

  1. Sliver 容器默认滚动方向为垂直方向 (column),如果希望实现水平的 Sliver 容器,可以通过增加 sliver-direction: row 来实现。
  2. 渲染容器节点滚动方向(主轴)的尺寸(width / height)必须指定,因为 Sliver 容器内部的元素并不会将主轴空间撑开,这也是与流式布局的盒子有差异的地方。
  3. Sliver 容器的子元素在滚动方向垂直的方向(交叉轴方向)上的尺寸会被自动拉伸为 Sliver 容器的尺寸。

API 参考

更多细节请跳转到 Sliver API 文档查看。