React如何渲染大資料量的列表?

繆宇發表於2019-03-03

我們經常會遇到這種需求,根據資料展示列表。這種程式碼估計你已經擼過成百上千次了。

但如果你需要同時展示成千上萬條資料呢,必然會造成瀏覽器卡頓,丟幀,甚至卡死的問題。

本文將介紹利用react-virtualized來高效渲染大資料量列表。

開始吧!

首先建立一個React 應用

create-react-app virtualization
複製程式碼

應用將展示1000條如下這樣的評論:

React如何渲染大資料量的列表?

我們引入第三方庫lorem-ipsum來生成模擬資料:

cd virtualization

npm install --save lorem-ipsum
複製程式碼

src/App.js 中引入 lorem-ipsum

import loremIpsum from `lorem-ipsum`;
複製程式碼

接下來創造一個1000條資料的陣列:

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個字評論

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,可以看到如下畫面:

React如何渲染大資料量的列表?

檢視元素,我們可以看到 DOM 上掛載了非常多的 div

React如何渲染大資料量的列表?

我們來測測效能

如果你用的是 Chrome,只需幾步,快速測試效能:

  • 開啟開發者工具
  • 按Command+Shift+P (Mac) or Control+Shift+P (Windows, Linux) 來開啟命令選單
  • 輸入 render,下拉框中選擇 Show Rendering
  • 點選 render 頁籤,FPS Meter 前打鉤。
  • 滾動列表
React如何渲染大資料量的列表?

我們可以看到,當滾動條滾動的時候,幀率從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

React如何渲染大資料量的列表?

檢視元素:

React如何渲染大資料量的列表?

可以看到只渲染了可見的元素。

效能怎麼樣呢?

用上面相同的方法測試:

React如何渲染大資料量的列表?

可以看到基本維持在60幀左右。效能槓槓的(^_^)

以上只是對react-virtualized的簡單應用,感興趣可以去試試!

感謝閱讀!

本文翻譯自Esteban HerreraRendering large lists with React Virtualized

相關文章