為什么使用react-window
1、不用全部加載出所有的DOM節(jié)點(diǎn)。默認(rèn)只渲染可視區(qū)域及可視區(qū)域外的一個(gè)節(jié)點(diǎn),此屬性可自定義設(shè)置。
2、可用于處理大型數(shù)據(jù)列表。當(dāng)使用在大型數(shù)據(jù)列表中,可避免因?yàn)閿?shù)據(jù)的更新而導(dǎo)致大量的重新渲染。
如何使用react-window
FixedSizeList(固定尺寸的列表)
import { FixedSizeList } from 'react-window';
/**
* 每個(gè)列表項(xiàng)的組件
* @param index:列表項(xiàng)的下標(biāo);style:列表項(xiàng)的樣式(此參數(shù)必須傳入列表項(xiàng)的組件中,否則會(huì)出現(xiàn)滾動(dòng)到下方出現(xiàn)空白的情況)
**/
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const Example = () => (
<FixedSizeList
height={150} // 列表可視區(qū)域的高度
itemCount={1000} // 列表數(shù)據(jù)長度
itemSize={35} // 列表行高
width={300} //列表可視區(qū)域的寬度
>
{Row}
</FixedSizeList>
);
VariableSizeList (可變尺寸列表)
import { VariableSizeList } from 'react-window';
const rowHeights = new Array(1000)
.fill(true)
.map(() => 25 + Math.round(Math.random() * 50));
const getItemSize = index => rowHeights[index]; // 此處采用隨機(jī)數(shù)作為每個(gè)列表項(xiàng)的高度
/**
* 每個(gè)列表項(xiàng)的組件
* @param index:列表項(xiàng)的下標(biāo);style:列表項(xiàng)的樣式(此參數(shù)必須傳入列表項(xiàng)的組件中,否則會(huì)出現(xiàn)滾動(dòng)到下方出現(xiàn)空白的情況)
**/
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
const Example = () => (
<VariableSizeList
height={150} // 列表可視區(qū)域的高度
itemCount={1000} // 列表數(shù)據(jù)長度
itemSize={getItemSize} // 設(shè)置列表項(xiàng)的高度
layout= "vertical" // (vertical/horizontal) 默認(rèn)為vertical,此為設(shè)置列表的方向
width={300}
>
{Row}
<VariableSizeList>
);
結(jié)合react-virtualized-auto-sizer使列表自適應(yīng)當(dāng)前頁面的寬高
使用AutoSizer可是列表寬高為當(dāng)前父組件的100%
import { FixedSizeList } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";
const Example = () => (
<AutoSizer>
{({ height, width }) => (
<FixedSizeList
className="List"
height={height}
itemCount={1000}
itemSize={35}
width={width}
>
{Row}
</FixedSizeList>
)}
</AutoSizer>
);
常見問題
在使用VariableSizeList 會(huì)遇到列表項(xiàng)樣式緩存沒有被清除導(dǎo)致行高一直和第一次可視區(qū)域里展示的一樣。可使用組件的屬性resetAfterIndex(index: number, shouldForceUpdate: boolean = true): void來清除樣式。
class Example extends Component {
constructor(props) {
super(props)
this.myRef = React.createRef()
}
......
render() {
......
<VariableSizeList
className='friends-list'
height={66}
itemCount={100}
itemSize={64}
itemSize={getItemSize}
ref={this.myRef}
width={260}>
{Row}
</VariableSizeList>
......
<button onClick={()=>{this.myRef.current.resetAfterIndex(0, false)}}>
清除樣式
</button>
......
}
}
參考文檔
react-window的github源碼:https://github.com/bvaughn/react-window
react-window的api使用文檔:https://react-window.now.sh/#/examples/list/fixed-size