咱们常常会遇到这种需求,根据数据展现列表。这种代码估计你已经撸过成百上千次了。css
但若是你须要同时展现成千上万条数据呢,必然会形成浏览器卡顿,丢帧,甚至卡死的问题。react
本文将介绍利用react-virtualized来高效渲染大数据量列表。git
首先建立一个React 应用github
create-react-app virtualization
复制代码
应用将展现1000条以下这样的评论:npm
咱们引入第三方库lorem-ipsum来生成模拟数据:数组
cd virtualization
npm install --save lorem-ipsum
复制代码
在 src/App.js
中引入 lorem-ipsum
:浏览器
import loremIpsum from 'lorem-ipsum'; 复制代码
接下来创造一个1000条数据的数组:markdown
const rowCount = 1000; class App extends Component { constructor() { super(); this.list = Array(rowCount).fill().map((val, idx) => { return { id: idx, name: 'John Doe', image: 'http://via.placeholder.com/40', text: loremIpsum({ count: 1, units: 'sentences', sentenceLowerBound: 4, sentenceUpperBound: 8 }) } }); } //... } 复制代码
以上每条数据都包含 id
、用户名
、图片
、随机生成4~8个字评论
。app
在 render()
中使用这个数组:工具
render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> <div className="list"> {this.list.map(this.renderRow.bind(this))} </div> </div> ); } 复制代码
增长 renderRow()
来创造列:
renderRow(item) { return ( <div key={item.id} className="row"> <div className="image"> <img src={item.image} alt="" /> </div> <div className="content"> <div>{item.name}</div> <div>{item.text}</div> </div> </div> ); } 复制代码
在 src/App.css
中加点样式:
.list {
padding: 10px;
}
.row {
border-bottom: 1px solid #ebeced;
text-align: left;
margin: 5px 0;
display: flex;
align-items: center;
}
.image {
margin-right: 10px;
}
.content {
padding: 10px;
}
复制代码
好了,启动项目 yarn start
,能够看到以下画面:
查看元素,咱们能够看到 DOM
上挂载了很是多的 div
:
若是你用的是 Chrome,只需几步,快速测试性能:
render
,下拉框中选择 Show Rendering
。render
页签,FPS Meter
前打钩。咱们能够看到,当滚动条滚动的时候,帧率从60掉到了38左右。这仍是只有1000条数据状况,若是再增大数据,浏览器会出现卡顿,甚至卡死。
接着咱们来看看react-virtualized是如何提升性能的?
核心原理:只渲染你所见的。
上面的应用渲染了1000条评论,但屏幕只为你展现了10来条数据,那另外990条的渲染就是浪费的。
若是咱们只渲染可见的评论,当鼠标滚动查看更多的时候,将新的节点替换旧的节点。这样就完美解决了性能瓶颈的问题。
首先在 src/App.js
中,引入 List
组件:
import { List } from "react-virtualized"; 复制代码
替换 render()
原有代码:
<div className="list">
{this.list.map(this.renderRow.bind(this))}
</div>
复制代码
使用 List
组件
const listHeight = 600; const rowHeight = 50; const rowWidth = 800; //... <div className="list"> <List width={rowWidth} height={listHeight} rowHeight={rowHeight} rowRenderer={this.renderRow.bind(this)} rowCount={this.list.length} /> </div> 复制代码
改写 renderRow()
:
renderRow({ index, key, style }) { return ( <div key={key} style={style} className="row"> <div className="image"> <img src={this.list[index].image} alt="" /> </div> <div className="content"> <div>{this.list[index].name}</div> <div>{this.list[index].text}</div> </div> </div> ); } 复制代码
启动应用 yarn start
:
查看元素:
能够看到只渲染了可见的元素。
用上面相同的方法测试:
能够看到基本维持在60帧左右。性能杠杠的(^_^)
以上只是对react-virtualized的简单应用,感兴趣能够去试试!
本文翻译自Esteban Herrera的Rendering large lists with React Virtualized