React.Component 與 React.PureComponent(React之性能優化)
前言
先說說 shouldComponentUpdate
提起React.PureComponent,我們還要從一個生命周期函數 shouldComponentUpdate 說起,從函數名字我們就能看出來,這個函數是用來控制組件是否應該被更新的。
React.PureComponent 通過prop和state的
淺對比
來實現shouldComponentUpate()。
簡單來說,這個生命周期函數返回一個布爾值。
如果返回true,那麽當props或state改變的時候進行更新;
如果返回false,當props或state改變的時候不更新,默認返回true。
(這裏的更新不更新,其實說的是執不執行render函數,如果不執行render函數,那自然該組件和其子組件都不會重新渲染啦)
重寫shouldComponentUpdate可以提升性能
,它是在重新渲染過程開始前
觸發的。當你明確知道組件不需要更新的時候,在該生命周期內返回false就行啦!
下面是一個重寫shouldComponentUpdate的例子:
class CounterButton extends React.Component { state={ count: 1 } shouldComponentUpdate(nextProps, nextState) { const {color}=this.props; const {count}=this.state; if (color !== nextProps.color) { return true; } // 重寫shouldComponentUpdate若將此處count相關邏輯註釋則count變化頁面不渲染 // if (count !== nextState.count) { // return true; // } return false; } render() { const {color}=this.props; const {count}=this.state; return ( <button style={{color}} onClick={() => this.setState(state => ({count: state.count + 1}))} > Count: {count} </button> ); } }
React.Component 與 React.PureComponent
言歸正傳,接下來說我們今天要討論的React.Component 與 React.PureComponent。
通常情況下,我們會使用ES6的class關鍵字來創建React組件:
class MyComponent extends React.Component {
// some codes here ...
}
但是,你也可以創建一個繼承React.PureComponent的React組件,就像這樣
class MyComponent extends React.PureComponent { // some codes here }
那麽,問題來了,這兩種方式有什麽區別呢?
繼承PureComponent時,不能再重寫shouldComponentUpdate,否則會引發警告(報錯截圖就不貼了,怪麻煩的)
Warning: CounterButton has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.
繼承PureComponent時,進行的是淺比較,也就是說,如果是引用類型的數據,只會比較是不是同一個地址
,而不會比較
具體這個地址存的數據是否完全一致
class ListOfWords extends React.PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
}
class WordAdder extends React.Component {
state = {
words: ['adoctors','shanks']
};
handleClick = () => {
const {words} = this.state;
words.push('tom');
this.setState({words});
console.log(words)
}
render() {
const {words}=this.state;
return (
<div>
<button onClick={this.handleClick}>click</button>
<ListOfWords words={words} />
</div>
);
}
}
上面代碼中,無論你怎麽點擊按鈕,ListOfWords渲染的結果始終沒變化,原因就是WordAdder的word的引用地址始終是同一個。
淺比較會忽略屬性或狀態突變的情況,其實也就是,數據引用指針沒變而數據被改變的時候,也不新渲染組件。但其實很大程度上,我們是希望重新渲染的。所以,這就需要開發者自己保證避免數據突變。
如果想使2中的按鈕被點擊後可以正確渲染ListOfWords,也很簡單,在WordAdder的handleClick內部,將 const words = this.state.words;
改為const words = this.state.words.slice(0);(這時的words是在原來state的基礎上復制出來一個新數組,所以引用地址當然變啦)
React.Component 與 React.PureComponent(React之性能優化)