咱們常常會遇到這種需求,根據數據展現列表。這種代碼估計你已經擼過成百上千次了。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