参考文档

说明:

react-virtualized是一个实现虚拟列表较为优秀的组件库,react-virtualized提供了一些基础组件用于实现虚拟列表,虚拟网格,虚拟表格等等,它们都可以减小不必要的dom渲染。此外还提供了几个高阶组件,可以实现动态子元素高度,以及自动填充可视区等等。

react-virtualized的基础组件包含:

  • Grid:用于优化构建任意网状的结构,传入一个二维的数组,渲染出类似棋盘的结构。
  • List:List是基于Grid来实现的,但是是一个维的列表,而不是网状。
  • Table:Table也是基于Grid来实现,表格具有固定的头部,并且可以在垂直方向上滚动
  • Masonry:同样可以在水平方向,也可以在垂直方向滚动,不同于Grid的是可以自定义每个元素的大小,或者子元素的大小也可以是动态变化的
  • Collection:类似于瀑布流的形式,同样可以水平和垂直方向滚动。

Tip:
值得注意的是这些基础组件都是继承于React中的PureComponent,因此当state变化的时候,只会做一个浅比较来确定重新渲染与否。

优化长列表的原理:
用数组保存所有列表元素的位置,只渲染可视区内的列表元素,当可视区滚动时,根据滚动的offset大小以及所有列表元素的位置,计算在可视区应该渲染哪些元素。

实现步骤:

  1. 首先确定长列表所在父元素的大小,父元素的大小决定了可视区的宽和高
  2. 确定长列表每一个列表元素的宽和高,同时初始的条件下计算好长列表每一个元素相对于父元素的位置,并用一个数组来保存所有列表元素的位置信息
  3. 首次渲染时,只展示相对于父元素可视区内的子列表元素,在滚动时,根据父元素的滚动的offset重新计算应该在可视区内的子列表元素。这样保证了无论如何滚动,真实渲染出的dom节点只有可视区内的列表元素。
  4. 假设可视区内能展示5个子列表元素,及时长列表总共有1000个元素,但是每时每刻,真实渲染出来的dom节点只有5个。

  5. 1. Grid的使用

    ```javascript import React, { useState, useRef } from ‘react’ import { Grid } from ‘react-virtualized’;

function App(props) { const list = [ [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’], [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’], [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’], [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’], [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’], [‘Jony yu’, ‘Software Engineer’, ‘Shenzhen’, ‘CHINA’, ‘GUANGZHOU’] ]; function cellRenderer({ columnIndex, key, rowIndex, style }) { return (

{list[rowIndex][columnIndex]}
) } return( ); }

export default App

  1. <a name="cJHpc"></a>
  2. ### 2. List的使用
  3. ```javascript
  4. import React, { useState, useRef } from 'react'
  5. //CellMeasurer 高阶组件,用来计算每个Cell的高度
  6. //CellMeasurerCache 计算Cell行高,填充父亲高度
  7. import { List, AutoSizer, CellMeasurer, CellMeasurerCache } from 'react-virtualized';
  8. //创建一个默认的Cache用来指定cell默认行高
  9. const cache = new CellMeasurerCache({ defaultHeight: 30, fixedWidth: true })
  10. function App(props) {
  11. const rowCount = 1000;
  12. const list = Array(rowCount).fill().map(() => {
  13. return {
  14. units: '子元素太长,换行后改变了子元素的高度后无法子适应,也就是说仅仅通过基础的组件List是不支持子元素的高度动态改变的场景子元素太长,换行后改变了换行后改变了换行后改变了换行后改变了换行后改变了换行后改变了换行后改变了aaaaaaa',
  15. }
  16. })
  17. function rowRenderer({
  18. key,
  19. index, //索引,第几条数据
  20. style, //样式
  21. parent //父亲
  22. }) {
  23. return (
  24. <CellMeasurer
  25. cache={cache}
  26. key={key}
  27. parent={parent}
  28. rowIndex={index}
  29. style={style}
  30. >
  31. <div
  32. style={style}
  33. >
  34. {list[index].units}
  35. </div>
  36. </CellMeasurer>
  37. )
  38. }
  39. return (<div style={{height:'100%'}}>
  40. {/*AutoSizer 让List的宽度由父亲宽度撑开*/}
  41. <AutoSizer>
  42. {({ height, width }) => (
  43. <List
  44. width={width} //List总宽度
  45. height={height} //List总高度
  46. rowCount={list.length} //总行数
  47. rowHeight={cache.rowHeight} //行高
  48. rowRenderer={rowRenderer} //渲染每一行使用的函数
  49. deferredMeasurementCache={cache} //默认cellcache
  50. />
  51. )}
  52. </AutoSizer>
  53. </div>
  54. )
  55. }
  56. export default App

3. 无限滚动

参考文档
参照资料中的 test-react-virtualized-master.zip