這篇文章主要介紹了React之PureComponent的介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
# React在渲染出的UI內部建立並維護了一個內層的實作方式,它包含了從元件傳回的React元素。這種實作方式使得React避免了一些不必要的建立和關聯DOM節點,因為這樣做可能比直接操作JavaScript物件更慢一些,它被稱為「虛擬DOM」。
當一個元件的props或state改變時,React會透過比較新回傳的元素和先前渲染的元素來決定是否有必要更新實際的DOM。當他們不相等時,React會更新DOM。
在某些情況下,你的元件可以透過重寫這個生命週期函數shouldComponentUpdate來提升速度, 它是在重新渲染過程開始前觸發的。這個函數預設回傳true,可使React執行更新:
shouldComponentUpdate(nextProps, nextState) { return true; }
如果想讓元件只在props.color
或state.count
的值變化時重新渲染,你可以像下面這樣設定shouldComponentUpdate
:
class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } }
在以上程式碼中,shouldComponentUpdate
只檢查props.color
和state.count
的變化。如果這些值沒有變化,元件就不會更新。當你的元件變得更加複雜時,你可以使用類似的模式來做一個“淺比較”,用來比較屬性和值以判定是否需要更新元件。這種模式十分常見,因此React提供了一個輔助物件來實作這個邏輯 - 繼承自React.PureComponent
。以下程式碼可以更簡單的實作相同的操作:
class CounterButton extends React.PureComponent { constructor(props) { super(props); this.state = {count: 1}; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } }
當元件更新時,如果元件的props 和state 都沒發生改變, render 方法就不會觸發,省去Virtual DOM 的生成與比對過程,達到提升效能的目的。具體就是 React 自動幫我們做了一層淺比較:
if (this._compositeType === CompositeTypes.PureClass) { shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); }
而 shallowEqual 又做了什麼呢?會比較Object.keys(state | props) 的長度是否一致,每一個key 是否兩者都有,並且是否是一個引用,也就是只比較了第一層的值,確實很淺,所以深層的嵌套數據是對比不出來的。
大部分情況下,你可以使用React.PureComponent而不必寫你自己的shouldComponentUpdate,它只做一個淺比較。但是由於淺比較會忽略屬性或狀態突變的情況,此時你不能使用它。
class ListOfWords extends React.PureComponent { render() { return <p>{this.props.words.join(',')}</p>; } } class WordAdder extends React.Component { constructor(props) { super(props); this.state = { words: ['marklar'] }; this.handleClick = this.handleClick.bind(this); } handleClick() { // This section is bad style and causes a bug const words = this.state.words; words.push('marklar'); this.setState({words: words}); } render() { return ( <p> <button onClick={this.handleClick} /> <ListOfWords words={this.state.words} /> </p> ); } }
在ListOfWords中,this.props.words是WordAdder中傳入的其state的一個引用。雖然在WordAdder的handelClick方法中被改變了,但是對於ListOfWords來說,其引用是不變的,從而導致並沒有被更新。
在上面的問題中可以發現,當一個資料是不變資料時,可以使用一個參考。但是對於一個易變資料來說,不能使用引用的方式給到PureComponent。簡單來說,就是我們在PureComponent外層來修改其使用的資料時,應該給其賦值一個新的物件或引用,以便確保其能夠進行重新渲染。例如上面範例中的handleClick可以透過以下幾種來進行修改從而確認正確的渲染:
handleClick() { this.setState(prevState => ({ words: prevState.words.concat(['marklar']) })); } 或者 handleClick() { this.setState(prevState => ({ words: [...prevState.words, 'marklar'], })); }; 或者针对对象结构: function updateColorMap(oldObj) { return Object.assign({}, oldObj, {key: new value}); }
Immutable.js是解決這個問題的另一種方法。它透過結構共享提供不可突變的,持久的集合:
不可突變:一旦創建,集合就不能在另一個時間點改變。
持久性:可以使用原始集合和一個突變來建立新的集合。原始集合在新集合建立後仍然可用。
結構共享:新集合盡可能多的使用原始集合的結構來創建,以便將複製操作降至最少從而提升效能。
// 常见的js处理 const x = { foo: 'bar' }; const y = x; y.foo = 'baz'; x === y; // true // 使用 immutable.js const SomeRecord = Immutable.Record({ foo: null }); const x = new SomeRecord({ foo: 'bar' }); const y = x.set('foo', 'baz'); x === y; // false
PureComponent
真正起作用的,只是在一些純展示元件上,複雜元件使用的話shallowEqual
那一關基本上就過不了。另外在使用的過程中為了確保能夠正確的渲染,記得 props
和 state
不能使用同一個引用哦。
以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!
相關推薦:
以上是React之PureComponent的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!