gmfe / Think

观麦前端团队的官方博客
68 stars 3 forks source link

记虚拟列表优化 #64

Open liyatang opened 5 years ago

liyatang commented 5 years ago

由于描述的略简单,深入请细聊

结论是

背景

一份大数据 skus

需要把 skus 分组展示

同时有很多其他入口会对 skus 做过滤,影响这份大数据

需要接入虚拟列表

问题

问题1

接入虚拟列表后会使 rowRenderer 没有因为 item 依赖数据的更新而更新

原因是虚拟列表的机制,这里不做细致的解答,大家看文档吧。

下面的代码假设 dataA 更新了,renderItem 没有运行,估没有更新,界面不正确

// 伪代码

renderItem = ({index, key, style}) => {
  return (
    <div
      key={key}
      style={style}
      item={skus[index]}
    >
    ...巴拉巴拉,其他代码,假设依赖了数据 dataA
    </div>
  )
}

<VList
  rowRenderer={this.renderItem}
/>

解决办法是

1 给 VList 换个key,比较暴力,不推荐

2 renderItem 返回一个组件,让组件自己去相应 dataA 的数据变更。具体 Item 怎么响应不过多介绍。

// 伪代码

renderItem = ({index, key, style}) => {
  return (
    <Item
      key={key}
      style={style}
      item={skus[index]}
    />
  )
}

<VList
  rowRenderer={this.renderItem}
/>

问题2

上面介绍过 skus 是需要分组展示,把 skus 转成 groupSkus。

同时还有各种过滤入口,会对 skus 做过滤,同时再生成新的 groupSkus,还得把虚拟列表滚到最开始

这样就会把业务和虚拟列表的耦合增加. 首先生成 groupSkus 耦合,滚到开始耦合

解决方案是:通过一个属性来告知虚拟列表数据有更新。 想法来源于 extraData

通过 extraData 的变化来告知虚拟列表数据有变更啦,需要重新处理数据

<VList
  rowRenderer={this.renderItem}
  extraData={依赖a+依赖b+依赖c}
/>

当然通过换 key 也是可以的,不建议。