使用React处理数据相对来说比较容易,因为React的设计就是把数据当作状态。但是当你需要处理的数据量很大的时候,麻烦就来了。比如你要处理一个包含500-1000条记录的数据集,这会产生巨大的计算量并导致性能问题。下面我们将学习如何使用虚拟列表来“看起来”渲染了一个长列表。
我们将使用React Virtualized组件来实现我们的需求。它让我们可以以很小的代价渲染大集合数据。
设置
React Virtualized官方已经有很详细的介绍了,可以去它们的github去看看。
我们需要大量的数据,下面我们就来造一些。
1 | function createRecord(count) { |
下面,我们设置一个数字来创造我们需要的数据:
const records = createRecord(1000);
好了,现在我们有需要渲染的数据了。
创建一个虚拟列表
这里是我们创建的一个列表,我们引入使用了库提供的一些展示样式,本篇post不讨论这个。
现在开始感受一下这个demo,速度超级快,是不是?
你可能想知道这背后到底发生了什么,结果发现是一系列很疯狂和酷的sizing、positioning、transform和transitions,是这些技术让一条条记录进入/离开可视区。数据都在那里并渲染了,React Virtualized创建了一个window,当用户scroll的时候,一条条记录将滑入/出我们的视野。
为了渲染虚拟列表,我们需要List组件,它内部渲染了一个Grid组件。
首先,我们从设置rowRenderer,开始,它是负责渲染单挑数据的组件。
1 | rowRenderer = ({ index, isScrolling, key, style }) => { |
它返回一个包含两个div的div,里面的两个div分别是username和email`。可以看出,这是一个简单的展示用户信息的列表。
rowRenderer接受几个参数,下面是这些参数的细节:
index: 记录的数值IDisScrolling: 代表List组件是否发生scrollingisVisible: 代表这条数据是否在可视区内key: 这条记录在数组中的位置parent: 定义这个列表是否是另一个列表的parent/childstyle: 定位这条数据的style对象
下面我们再深入了解一些rowRenderer函数,我们把它放到List组件中:
1 | <List |
你可能注意到这里的几个参数:
rowCount: 接收代表列表长度的数字width: 列表的宽度height: 列表的高度rowHeight: 每条数据的高度rowRenderer: 用来渲染每条数据的模板,我们将传入之前定义的rowRenderer函数overscanRowCount:
用来渲染用户scroll方向额外的数据,防止用户滑动太快,虚拟内容来不及渲染。
最后,代码应该是这样的:
1 | const { List } = ReactVirtualized |
Cell measure
文档里介绍,cell
measure是一个高阶组件,用来暂时渲染列表。现在我们还看不到它,但数据已经在里面被处理并准备好展示了。
什么时候我们需要关心cell measure?最常见的use
case是当我们需要动态计算rowHeight的时候。React
Virtualized在渲染每一行的时候,会缓存它们的高度值,这样当数据滑出可视区的时候我们也不用再计算它的高度——不管里面的内容是什么,高度都是对的。
首先,我们创建自己的缓存cache,在我们组件的constructor里用CellMeasureCache:
1 | constructor() { |
当我们设置List组件的时候,把cache带上:
1 | <List |
传给deferredMeasurementCache的值会被用来暂时渲染数据,接着——当rowHeight的计算结果出来的时候——额外的行会流入,就像它们一直在那里。
接着我们将在rowRenderer函数里使用CellMeasure替换我们之前的div:
1 | rowRenderer = ({ index, parent, key, style }) => { |
现在数据已经被获取、缓存并准备好展示在虚拟window里了!
虚拟table
虽然本片post主要说列表,但万一当我们需要渲染table怎么办?React
Virtualized也帮我们做了这件事情。这时我们需要使用Table和Column组件。
下面是代码:
1 | class App extends React.Component { |
这个Table组件包括下面的参数:
widthheightheaderHeightrowHeightrowCountrowGetter: 返回这行的数据
如果看一下Column组件,你会发现我们设置了一个dataKey参数。它是每条数据拥有的独一无二的id。
总结
希望这篇post可以帮你了解React
Virtualized可以做哪些事情,它如何让列表渲染变得很快,并如何在项目中使用它。
我们只讨论了皮毛,这个库覆盖了更多的use case,如在scroll的时候为记录generate
placeholders、实时获取/缓存数据的无限加载组件等等。
它将给你很多可以play with的东西!
此外,这个包维护的很好,实际上你可以加入Slack group来跟踪这个项目,贡献它,和其他folks取得联系。
还有一条值得注意的是,React Virtualized在StackOverflow上有它自己的标签,这是一个寻找问题的答案的地方,也可以po出你的问题。