圖解ES6中的React生命週期

扇子醬發表於2017-11-12

圖解ES6中的React生命週期

前言

如果將React的生命週期比喻成一隻螞蟻爬過一根吊繩,那麼這隻螞蟻從繩頭爬到繩尾,就會依次觸動不同的卡片掛鉤。在React每一個生命週期中,也有類似卡片掛鉤的存在,我們把它稱之為‘鉤子函式’。那麼在React的生命週期中,到底有哪些鉤子函式?React的生命週期又是怎樣的流程?今天我給大家來總結總結

React 生命週期

圖解ES6中的React生命週期

如圖,React生命週期主要包括三個階段:初始化階段、執行中階段和銷燬階段,在React不同的生命週期裡,會依次觸發不同的鉤子函式,下面我們就來詳細介紹一下React的生命週期函式

一、初始化階段

1、設定元件的預設屬性
static defaultProps = {
    name: 'sls',
    age:23
};
//or
Counter.defaltProps={name:'sls'}
複製程式碼
2、設定元件的初始化狀態
constructor() {
    super();
    this.state = {number: 0}
}
複製程式碼
3、componentWillMount()

元件即將被渲染到頁面之前觸發,此時可以進行開啟定時器、向伺服器傳送請求等操作

4、render()

元件渲染

5、componentDidMount()

元件已經被渲染到頁面中後觸發:此時頁面中有了真正的DOM的元素,可以進行DOM相關的操作

二、執行中階段

1、componentWillReceiveProps()

元件接收到屬性時觸發

2、shouldComponentUpdate()

當元件接收到新屬性,或者元件的狀態發生改變時觸發。元件首次渲染時並不會觸發

shouldComponentUpdate(newProps, newState) {
    if (newProps.number < 5) return true;
    return false
}
//該鉤子函式可以接收到兩個引數,新的屬性和狀態,返回true/false來控制元件是否需要更新。
複製程式碼

一般我們通過該函式來優化效能:

一個React專案需要更新一個小元件時,很可能需要父元件更新自己的狀態。而一個父元件的重新更新會造成它旗下所有的子元件重新執行render()方法,形成新的虛擬DOM,再用diff演算法對新舊虛擬DOM進行結構和屬性的比較,決定元件是否需要重新渲染

無疑這樣的操作會造成很多的效能浪費,所以我們開發者可以根據專案的業務邏輯,在shouldComponentUpdate()中加入條件判斷,從而優化效能

例如React中的就提供了一個PureComponent的類,當我們的元件繼承於它時,元件更新時就會預設先比較新舊屬性和狀態,從而決定元件是否更新。值得注意的是,PureComponent進行的是淺比較,所以元件狀態或屬性改變時,都需要返回一個新的物件或陣列

3、componentWillUpdate()

元件即將被更新時觸發

4、componentDidUpdate()

元件被更新完成後觸發。頁面中產生了新的DOM的元素,可以進行DOM操作

三、銷燬階段

1、componentWillUnmount()

元件被銷燬時觸發。這裡我們可以進行一些清理操作,例如清理定時器,取消Redux的訂閱事件等等。

有興趣的同學也可以用下面的程式碼進行測試

廢話少說,放碼過來!

import React from 'react'
import ReactDOM from 'react-dom';

class SubCounter extends React.Component {
    componentWillReceiveProps() {
        console.log('9、子元件將要接收到新屬性');
    }

    shouldComponentUpdate(newProps, newState) {
        console.log('10、子元件是否需要更新');
        if (newProps.number < 5) return true;
        return false
    }

    componentWillUpdate() {
        console.log('11、子元件將要更新');
    }

    componentDidUpdate() {
        console.log('13、子元件更新完成');
    }

    componentWillUnmount() {
        console.log('14、子元件將解除安裝');
    }

    render() {
        console.log('12、子元件掛載中');
        return (
                <p>{this.props.number}</p>
        )
    }
}

class Counter extends React.Component {
    static defaultProps = {
        //1、載入預設屬性
        name: 'sls',
        age:23
    };

    constructor() {
        super();
        //2、載入預設狀態
        this.state = {number: 0}
    }

    componentWillMount() {
        console.log('3、父元件掛載之前');
    }

    componentDidMount() {
        console.log('5、父元件掛載完成');
    }

    shouldComponentUpdate(newProps, newState) {
        console.log('6、父元件是否需要更新');
        if (newState.number<15) return true;
        return false
    }

    componentWillUpdate() {
        console.log('7、父元件將要更新');
    }

    componentDidUpdate() {
        console.log('8、父元件更新完成');
    }

    handleClick = () => {
        this.setState({
            number: this.state.number + 1
        })
    };

    render() {
        console.log('4、render(父元件掛載)');
        return (
            <div>
                <p>{this.state.number}</p>
                <button onClick={this.handleClick}>+</button>
                {this.state.number<10?<SubCounter number={this.state.number}/>:null}
            </div>
        )
    }
}
ReactDOM.render(<Counter/>, document.getElementById('root'));
複製程式碼

相關文章