React 全家桶之 react 性能優化

react 整個生命週期大概分爲三個階段:掛載階段、更新階段、銷燬階段,我們在談 react 優化的時候主要還是針對更新階段。

render

我們先來回顧一下 render 函數做了什麼事情

  • 構建 Virtual DOM 樹
  • diff 出差異化節點
  • 根據 Virtual DOM 樹解析出 html 結構
  • 將 html 結構掛載到真是 DOM 樹上

shouldComponentUpdate

該函數位於更新階段,在 render 之前。表示本次更新是否影響到當前組件,默認爲 true,會執行後續的 render 函數,即使最後經過 diff 發現沒有需要更新的地方。

所以我們可以在組件的 shouldComponentUpdate 鉤子裏,自己來判斷要不要更新,如果不需要就 return false,這樣就少了構建 Virtual Dom、diff 這些階段了,對性能提升有一定的幫助。如

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 99
        };
    }
    shouldComponentUpdate(nextProps, nextState) {
        if (nextState.count === this.state.count) {
            return false; // 不參與 render 和 diff 過程
        }
        return true;
    }
    render () {
        return (
        <div id="container">{ this.state.count }</div>
        )
    }
}

PureComponent

上面的例子中,我們在 shouldComponentUpdate 中手動判斷了當前組件是否需要更新的邏輯。有了 PureComponent,想這種簡單的組件我們就不需要自己判斷了,直接讓組件繼承 React.PureComponent 就行了,應該 PureComponent 內部已經幫我們執行了 shouldComponentUpdate,如果發現 props 和 state 都沒有變化,那麼 return false,不參與更新。

但是注意:PureComponent 中的判斷是一種淺比較,也就是說如果你的 data 中的屬性全部只有一層(屬性值是基本類型),那麼沒問題。但是如果屬性值裏面是一個 Object 或者是一個 Array,那麼屬性值內部的變化,PureComponent 就無法感知了。所以組件的屬性值比較複雜的話,建議不要用 PureComponent。

屬性傳遞

在組件上綁定函數一般有以下幾種方式

  • constructor 中綁定 this:this.handleClick = this.handleClick.bind(this);使用 <button onClick={this.handleClick}></button>
  • 使用時綁定:<button onClick={this.handleClick.bind(this)}
  • 箭頭函數:<button onClick={() => {this.handleClick()}}
  • 組件本身方法使用箭頭函數:handleClick = () => {};使用 <button onClick={this.handleClick}></button>

推薦 1 和 4,2 和 3 在組件每次執行 render 時都會生成一個新的函數,在 diff 階段會經過淺比較判斷出屬性需要更新

合理利用 key

在更新階段,react 會通過組件的 key 值來進行新老節點的匹配。如果匹配到了,只需要更新屬性或者調整位置就行了,避免了組件的重新掛載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章