詳解在React.js中使用PureComponent的重要性和使用方式
一、介紹PureComponent
React 15.3在2016.06.29發(fā)布了,這個版本最值得關(guān)注的是支持了 React.PureComponent ,它取代了之前的 pure-render-mixin 。在本文中,我們將討論 PureComponent 的重要性和使用場景。
React.PureComponent最重要的一個用處就是優(yōu)化React應(yīng)用,這很容易快速地實現(xiàn)。使用 React.PureComponent 對性能的提升是非??捎^的,因為它減少了應(yīng)用中的渲染次數(shù)。
PureComponent改變了生命周期方法 shouldComponentupdate
,并且它會自動檢查組件是否需要重新渲染。這時,只有PureComponent檢測到 state
或者 props
發(fā)生變化時,PureComponent才會調(diào)用 render
方法,因此,你不用手動寫額外的檢查,就可以在很多組件中改變 state
, 例如:
if (this.state.someVal !== computedVal) { this.setState({ someVal: computedVal }) }
根據(jù)React源碼,如果組件是純組件(Pure Component),那么一下比較是很容易理解的:
if (this._compositeType === CompositeTypes.PureClass) { shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState); }
其中, shadowEqual
只會"淺"檢查組件的 props
和 state
,這就意味著嵌套對象和數(shù)組是不會被比較的。
深比較操作是非常昂貴的,同時,如果這個組件還是純組件(PureComponent),那么深比較將會更浪費。另外,你也可以使用 shouldComponentUpdate
來手動確定組件是否需要重新渲染。最簡單的方式就是直接比較 props
或 state
:
shouldComponentUpdate(nextProps, nextState) { return nextProps.user.id === props.user.id; }
除此之外,你可以使用 immutable 屬性。這種情況下,屬性的比較是非常容易的,因為已存在的對象不會發(fā)生改變,取而代之的是重新創(chuàng)建新的對象。其中, Immutable.js 就是非常好的Immutable庫。
二、使用PureComponent
PureComponent節(jié)約了我們的時間,避免了多余的代碼。那么,掌握如何正確使用它是非常重要的,否則如果使用不當,它就無法發(fā)揮作用。因為PureComponent僅僅是淺比較(shadow comparison),所以改變組件內(nèi)部的 props
或者 state
,它將不會發(fā)揮作用。例如,讓我們想想這樣一種情況,父組件有一個render方法和一個click處理方法:
handleClick() { let {items} = this.state items.push('new-item') this.setState({ items }) } render() { return ( <div> <button onClick={this.handleClick} /> <ItemList items={this.state.items} /> </div> ) }
如果ItemList是純組件(PureComponent),那么這時它是不會被渲染的,因為盡管 this.state.items
的值發(fā)生了改變,但是它仍然指向同一個對象的引用。但是,通過移除可變對象就很容易改變這種情況,使之能夠正確被渲染。
handleClick() { this.setState(prevState => ({ words: prevState.items.concat(['new-item']) })); }
如果一個純組件(PureComponent)的 state 或 props 引用了一個新對象,那么這個組件就會被重新渲染(re-render)。這暗示著,如果不想損失PureComponent的優(yōu)點,那么我們應(yīng)該避免以下的結(jié)構(gòu):
<Entity values={this.props.values || []}/>
如上面代碼,新數(shù)組,即便是空數(shù)組,總是會迫使組件重新渲染。為了避免這個問題,你可以使用 defaultProps
,它包含了一個屬性的初始化空狀態(tài)。解決這個問題的另一種方法如下:
<CustomInput onChange={e => this.props.update(e.target.value)} />
在純組件(PureComponent)被創(chuàng)建時,因為函數(shù)的新對象被創(chuàng)建了,所以它會獲得新數(shù)據(jù),并且重新渲染。解決這個問題最簡單的方法就是: 在組件的 constructor 方法中使用 bind 。
constructor(props) { super(props) this.update = this.update.bind(this) } update(e) { this.props.update(e.target.value) } render() { return <MyInput onChange={this.update} /> }
同時,在JSX中,任何包含子元素(child elements)的組件, shallowEqual
檢查總會返回false。
請謹記:純組件忽略重新渲染時,不僅會影響它本身,而且會影響它的說有子元素,所以,使用PureComponent的最佳情況就是展示組件,它既沒有子組件,也沒有依賴應(yīng)用的全局狀態(tài)。
三、總結(jié)
事實上,如果你已經(jīng)意識到 shallowEqual
和 JS References
的特性,過渡到PureComponent是相當容易的。正常情況下,遷移的方式非常簡單,就像改變組件繼承的基類,從
class MyComponent extends Component {...}
到
class MyComponent extends PureComponent {...}
這樣不僅能平滑過渡,甚至可以提升性能。所以,我極力推薦所有人在開發(fā)應(yīng)用中使用PureComponent。
四、注意
在純組件有子組件的時候,所有基于 this.context 改變的子組件,在 this.context 改變時, 將不會重新渲染 ,除非在父組件(Parent ParentComponent)中聲明 contextTypes 。
本文翻譯至habrahabr。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解React Native開源時間日期選擇器組件(react-native-datetime)
本篇文章主要介紹了詳解React Native開源時間日期選擇器組件(react-native-datetime),具有一定的參考價值,有興趣的可以了解一下2017-09-09淺析history 和 react-router 的實現(xiàn)原理
react-router 版本更新非???但是它的底層實現(xiàn)原理確是萬變不離其中,在本文中會從前端路由出發(fā)到 react-router 原理總結(jié)與分享,本文對history 和 react-router實現(xiàn)原理講解的非常詳細,需要的朋友跟隨小編一起看看吧2023-08-08React?Native集成支付寶支付的實現(xiàn)方法
這篇文章主要介紹了React?Native集成支付寶支付的實現(xiàn)現(xiàn),ativeModules是JS代碼調(diào)用原生模塊的橋梁。所以,我們只需要在原生工程中集成支付寶和微信支付的sdk,然后使用NativeModules調(diào)用即可,需要的朋友可以參考下2022-02-02