React如何渲染大數據量的列表?

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

  • 打開開發者工具
  • 按Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux) 來打開命令菜單
  • 輸入 render,下拉框中選擇 Show Rendering
  • 點擊 render 頁籤,FPS Meter 前打鉤。
  • 滾動列表

咱們能夠看到,當滾動條滾動的時候,幀率從60掉到了38左右。這仍是隻有1000條數據狀況,若是再增大數據,瀏覽器會出現卡頓,甚至卡死。

接着咱們來看看react-virtualized是如何提升性能的?

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 HerreraRendering large lists with React Virtualized

相關文章
相關標籤/搜索