React.Component 與 React.PureComponent(React之性能優化)


前言 先說說 shouldComponentUpdate

提起React.PureComponent,我們還要從一個生命周期函數 shouldComponentUpdate 說起,從函數名字我們就能看出來,這個函數是用來控制組件是否應該被更新的。

簡單來說,這個生命周期函數返回一個布爾值,如果返回true,那么當props或state改變的時候進行更新;如果返回false,當props或state改變的時候不更新,默認返回true。(這里的更新不更新,其實說的是執不執行render函數,如果不執行render函數,那自然該組件和其子組件都不會重新渲染啦)

重寫shouldComponentUpdate可以提升性能,它是在重新渲染過程開始前觸發的。當你明確知道組件不需要更新的時候,在該生命周期內返回false就行啦!

下面是一個重寫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>
        );
    }
}

React.Component 與 React.PureComponent

言歸正傳,接下來說我們今天要討論的React.ComponentReact.PureComponent

通常情況下,我們會使用ES6的class關鍵字來創建React組件:

class MyComponent extends React.Component {
    // some codes here ...
}

但是,你也可以創建一個繼承React.PureComponent的React組件,就像這樣

class MyComponent extends React.PureComponent {
    // some codes here
}

那么,問題來了,這兩種方式有什么區別呢?

  1. 繼承PureComponent時,不能再重寫shouldComponentUpdate,否則會引發警告(報錯截圖就不貼了,怪麻煩的)

Warning: ListOfWords has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.

  1. 繼承PureComponent時,進行的是淺比較,也就是說,如果是引用類型的數據,只會比較是不是同一個地址,而不會比較具體這個地址存的數據是否完全一致

class ListOfWords extends React.PureComponent {
render() {
return

{this.props.words.join(',')}
;
}
}
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 (




);
}
}

上面代碼中,無論你怎么點擊按鈕,*ListOfWords*渲染的結果始終沒變化,原因就是*WordAdder*的word的引用地址始終是同一個。

3. 淺比較會忽略屬性或狀態突變的情況,其實也就是,數據引用指針沒變而數據被改變的時候,也不新渲染組件。但其實很大程度上,我們是希望重新渲染的。所以,這就需要開發者自己保證避免數據突變。
如果想使`2`中的按鈕被點擊后可以正確渲染*ListOfWords*,也很簡單,在*WordAdder*的*handleClick*內部,將 `const words = this.state.words;` 改為`const words = this.state.words.slice(0);` 就行啦~(這時的words是在原來state的基礎上復制出來一個新數組,所以引用地址當然變啦)

---------

此處博客,只是簡單做個記錄,再者就是思緒整理,增加印象。有誤之處,歡迎來噴。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM