React在進行渲染的時候會經(jīng)歷初次渲染和更新渲染,首次渲染是沒有真實的DOM操作快的,在更新渲染的時候,通過Virtual DOM,DOM Diff
比真實的DOM操作快,但是也存在需要優(yōu)化的情況
比如:我們更新了圖中DOM樹第3層的一塊(綠色),我們希望渲染的是DOM樹的最短路徑(綠色部分),但是React的默認做法的調(diào)用所有子組件的render,再與生成的虛擬DOM進行對比,如果不變則不更新,這里不變(黃色部分)的渲染和對比是需要優(yōu)化的部分
兩個性能優(yōu)化點
- 父組件更新默認觸發(fā)所有子組件更新
- 列表類型的組件默認更新方式非常復雜
解決方法
- 子組件執(zhí)行
shouldComponentUpdate()
,自行決定是否更新,React的優(yōu)化是基于shouldComponentUpdate
的,該生命周期默認返回true,所以一旦prop或state有任何變化,都會引起重新render - 給列表中的組件添加
key
屬性,不要使用默認的index
,因為一旦數(shù)組的索引發(fā)生變化,會觸發(fā)不必要的更新
詳解
React 針對組件的shouldComponentUpdate()
進行了封裝處理
React ES5提供了PureRenderMixin
的mixin
形式
import PureRenderMixin from 'react-addons-pure-render-mixin';
class FooComponent extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate =
PureRenderMixin.shouldComponentUpdate.bind(this);
}
}
React ES6新增了一個PureComponent
類,以 ES6 class 的方式方便地定義純組件(pure component)
,用于取代之的PureRenderMixin
用法是把繼承類從Component
換成PureComponent
即可,當組件更新時,如果組件的props,state
都沒發(fā)生改變,就不會觸發(fā)render
,省去了 Virtual DOM 的生成和比對過程,達到提升性能的目的
import React, { PureComponent } from 'react'
class Example extends PureComponent {
render() {
...
}
}
這里要注意的是:PureRenderMixin、PureComponent
內(nèi)進行的僅僅是淺比較對象(shallowCompare)
,如果我們的state
變?yōu)?/p>
state = {
value: { foo: 'bar' }
}
// 每次更改value值的時候進行:
this.setState({ value: newValue });
此時直接通過值的比較是行不通的,因為對象的引用關(guān)系,導致在子組件里面接受到的this.props.value 與 nextProps.value
永遠都是相等,就不會更新
解決方法
- 深比較: 原理與深拷貝類似,比較耗時,不推薦
- immutable.js:FaceBook官方提出的不可變數(shù)據(jù)解決方案,主要解決了復雜數(shù)據(jù)在deepClone和對比過程中性能損耗
總結(jié)
-
immutable.js
的思想其實是跟React的虛擬DOM是一致的,都是為了減少不必要的消耗,immutable.js
減少對象占用內(nèi)存,虛擬DOM減少了瀏覽器的重繪和重排版
React性能檢測工具 react-addons-perf
import Perf from 'react-addons-perf'
window.Perf = Perf // 掛載到全局變量方便使用
檢測方法,在瀏覽器控制臺輸入如下命令
開始記錄:Perf.start()
結(jié)束記錄:Perf.stop()
打印結(jié)果:printInclusive()
參考文章推薦
React組件性能調(diào)優(yōu)