React在進(jìn)行渲染的時候會經(jīng)歷初次渲染和更新渲染,首次渲染是沒有真實(shí)的DOM操作快的任柜,在更新渲染的時候,通過Virtual DOM,DOM Diff
比真實(shí)的DOM操作快,但是也存在需要優(yōu)化的情況
比如:我們更新了圖中DOM樹第3層的一塊(綠色)粥谬,我們希望渲染的是DOM樹的最短路徑(綠色部分),但是React的默認(rèn)做法的調(diào)用所有子組件的render辫塌,再與生成的虛擬DOM進(jìn)行對比漏策,如果不變則不更新,這里不變(黃色部分)的渲染和對比是需要優(yōu)化的部分
兩個性能優(yōu)化點(diǎn)
- 父組件更新默認(rèn)觸發(fā)所有子組件更新
- 列表類型的組件默認(rèn)更新方式非常復(fù)雜
解決方法
- 子組件執(zhí)行
shouldComponentUpdate()
臼氨,自行決定是否更新掺喻,React的優(yōu)化是基于shouldComponentUpdate
的,該生命周期默認(rèn)返回true,所以一旦prop或state有任何變化感耙,都會引起重新render - 給列表中的組件添加
key
屬性褂乍,不要使用默認(rèn)的index
,因?yàn)橐坏?shù)組的索引發(fā)生變化即硼,會觸發(fā)不必要的更新
詳解
React 針對組件的shouldComponentUpdate()
進(jìn)行了封裝處理
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
即可只酥,當(dāng)組件更新時褥实,如果組件的props,state
都沒發(fā)生改變,就不會觸發(fā)render
层皱,省去了 Virtual DOM 的生成和比對過程性锭,達(dá)到提升性能的目的
import React, { PureComponent } from 'react'
class Example extends PureComponent {
render() {
...
}
}
這里要注意的是:PureRenderMixin、PureComponent
內(nèi)進(jìn)行的僅僅是淺比較對象(shallowCompare)
叫胖,如果我們的state
變?yōu)?/p>
state = {
value: { foo: 'bar' }
}
// 每次更改value值的時候進(jìn)行:
this.setState({ value: newValue });
此時直接通過值的比較是行不通的草冈,因?yàn)閷ο蟮囊藐P(guān)系,導(dǎo)致在子組件里面接受到的this.props.value 與 nextProps.value
永遠(yuǎn)都是相等瓮增,就不會更新
解決方法
- 深比較: 原理與深拷貝類似怎棱,比較耗時,不推薦
- immutable.js:FaceBook官方提出的不可變數(shù)據(jù)解決方案绷跑,主要解決了復(fù)雜數(shù)據(jù)在deepClone和對比過程中性能損耗
總結(jié)
-
immutable.js
的思想其實(shí)是跟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)