React生命週期shouldComponentUpdate介紹及性能優化

React生命週期shouldComponentUpdate介紹及性能優化

在react開發中,經常需要對數據state狀態進行改變,但是這種方式每當setState的時候都會將所有的組件重新渲染一遍,這樣就會有重複渲染render的問題。

看如下圖組件樹:

默認情況下,當執行setState()方法時,react 會重新渲染整個組件樹,這造成不必要的性能開銷。
黃色的節點表示我們修改了數據的節點,我們希望只重新渲染這個部分,而其它藍色的節點是我們不希望重複渲染的。那麼怎麼解決呢?生命週期的shouldComponentUpdate就可以簡單解決。
在這裏插入圖片描述

shouldComponentUpdate介紹

shouldComponentUpdate(nextProps, nextState)

  • nextProps: 表示下一個props。
  • nextState: 表示下一個state的值。

官方API解釋道根據 shouldComponentUpdate() 的返回值,判斷 React 組件的輸出是否受當前 state 或 props 更改的影響。默認行爲是 state 每次發生變化組件都會重新渲染。大部分情況下,你應該遵循默認行爲。

shouldComponentUpdate(nextProps, nextState){
    //組件是否需要更新,需要返回一個布爾值,返回true則更新,返回flase不更新,這是一個關鍵點
    console.log('shouldComponentUpdate組件是否應該更新,需要返回布爾值',nextProps, nextState)
    return true
}

當 props 或 state 發生變化時,shouldComponentUpdate() 會在渲染執行之前被調用。返回值默認爲 true。首次渲染或使用 forceUpdate() 時不會調用該方法。

使用shouldComponentUpdate性能優化

React中props,state值的變化,會導致組件重新渲染。使用shouldComponentUpdate就是爲了減少render不必要的渲染。 返回布爾值,然後做 Virtual DOM 比較,並得出是否需要做真實 DOM 更新,儘管React的虛擬算法複雜度已經有了很多優化,但是在大規模組件更新時,依然會是個不必要的損耗。會帶來很多無必要的渲染併成爲性能瓶頸。接下來使用來這個生命週期來解決吧

例子:

import React, { Component } from 'react'
class Title extends Component {
    shouldComponentUpdate(nextProps){
        return nextProps.title!==this.props.title
    }
    render() {
        console.log("我是title組件")
        return (
            <div>
                標題:{this.props.title}
            </div>
        )
    }
}

class Count extends Component {
    render() {
        console.log("我是條數組件")
        return (
            <div>
                條數:{this.props.count}
            </div>
        )
    }
}

export default class Purememo extends Component {
    constructor(props){
        super(props)
        this.state={
            title:'shouldComponentUpdate使用',
            count:0
        }
    }
    componentDidMount(){
        setInterval(()=>{
            this.setState({
                count:this.state.count+1
            })
        },1000)
    }
    render() {
        return (
            <div>
                <Title title={this.state.title}></Title>
                <Count count={this.state.count}></Count>
            </div>
        )
    }
}

Purememo整個組件會重新渲染,如果不適用shouldComponentUpdate那麼Title,Count會一直渲染,但是使用shouldComponentUpdate後Title則不會發生渲染。

當然你也可以考慮使用內置的 React.PureComponent 組件,shouldComponentUpdate()。PureComponent 會對 props 和 state 進行淺層比較,並減少了跳過必要更新的可能性。不建議shouldComponentUpdate() 中進行深層比較或使用 JSON.stringify()。這樣非常影響效率,且會損害性能。

面對複雜的對象時,這樣的數據就沒有效果了,因爲在js中,object,array,function屬於引用類型,即使改變其中數據,他們指向的還是同一內存地址,所以採用上面的判斷就不行了。例如:

 obj: {
    age: 12,
    name: 'xiaoming',
    student: {
        count: 1
    }
}

解決方法有以下幾種:

  1. 使用setState改變數據之前,先採用es6中assgin進行拷貝,但是assgin只深拷貝的數據的第一層,所以說不是最完美的解決辦法。
const o2 = Object.assign({},this.state.obj)
    o2.student.count = '00000';
    this.setState({
        obj: o2,
    })

  1. 使用JSON.parse(JSON.stringfy())進行深拷貝,但是遇到數據爲undefined和函數時就會錯。
const o2 = JSON.parse(JSON.stringify(this.state.obj))
    o2.student.count = '00000';
    this.setState({
        obj: o2,
    })
  1. 使用react官方推薦的第三方庫:immutable.js進行項目的搭建。immutable中講究數據的不可變性,每次對數據進行操作前,都會自動的對數據進行深拷貝,項目中數據採用immutable的方式,可以輕鬆解決問題,但是又多了一套API去學習。
    在這裏插入圖片描述
    在這裏插入圖片描述
    關於immutable.js可參考
    精讀 Immutable 結構共享
    深入探究Immutable.js的實現機制(一)
    深入探究Immutable.js的實現機制(二)
    瞭解Clojure的持久變量

部分參考他人,侵刪

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章