天天看點

React元件生命周期小結React 生命周期相關函數更新方式一個React元件生命周期的測試例子

React 生命周期

前言

學習React,生命周期很重要,我們了解完生命周期的各個元件,對寫高性能元件會有很大的幫助.

Ract生命周期

React 生命周期分為三種狀态 1. 初始化 2.更新 3.銷毀

React元件生命周期小結React 生命周期相關函數更新方式一個React元件生命周期的測試例子
  • 初始化

1、getDefaultProps()

設定預設的props,也可以用dufaultProps設定元件的預設屬性.

2、getInitialState()

在使用es6的class文法時是沒有這個鈎子函數的,可以直接在constructor中定義this.state。此時可以通路this.props

3、componentWillMount()

元件初始化時隻調用,以後元件更新不調用,整個生命周期隻調用一次,此時可以修改state。

4、 render()

react最重要的步驟,建立虛拟dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。

5、componentDidMount()

元件渲染之後調用,隻調用一次。
  • 更新

6、componentWillReceiveProps(nextProps)

元件初始化時不調用,元件接受新的props時調用。

7、shouldComponentUpdate(nextProps, nextState)

react性能優化非常重要的一環。元件接受新的state或者props時調用,我們可以設定在此對比前後兩個props和state是否相同,如果相同則傳回false阻止更新,因為相同的屬性狀态一定會生成相同的dom樹,這樣就不需要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤其是在dom結構複雜的時候

8、componentWillUpdata(nextProps, nextState)

元件初始化時不調用,隻有在元件将要更新時才調用,此時可以修改state

9、render()

元件渲染

10、componentDidUpdate()

元件初始化時不調用,元件更新完成後調用,此時可以擷取dom節點。
  • 解除安裝

11、componentWillUnmount()

元件将要解除安裝時調用,一些事件監聽和定時器需要在此時清除。

結束語

以上就是React 的生命周期,大家可以自行寫下code測試一下,在這裡我就不貼code 了。

下面所寫的,隻适合前端的React。(React也支援後端渲染,而且和前端有點小差別,不過我沒用過。)

相關函數

簡單地說,React Component通過其定義的幾個函數來控制元件在生命周期的各個階段的動作。

在ES6中,一個React元件是用一個class來表示的(具體可以參考官方文檔),如下:

// 定義一個TodoList的React元件,通過繼承React.Component來實作
class TodoList extends React.Component {
  ...
}
                

這幾個生命周期相關的函數有:

constructor(props, context)
                

構造函數,在建立元件的時候調用一次。

void componentWillMount()
                

在元件挂載之前調用一次。如果在這個函數裡面調用setState,本次的render函數可以看到更新後的state,并且隻渲染一次。

void componentDidMount()
                

在元件挂載之後調用一次。這個時候,子主鍵也都挂載好了,可以在這裡使用refs。

void componentWillReceiveProps(nextProps)
                

props是父元件傳遞給子元件的。父元件發生render的時候子元件就會調用componentWillReceiveProps(不管props有沒有更新,也不管父子元件之間有沒有資料交換)。

bool shouldComponentUpdate(nextProps, nextState)
                

元件挂載之後,每次調用setState後都會調用shouldComponentUpdate判斷是否需要重新渲染元件。預設傳回true,需要重新render。在比較複雜的應用裡,有一些資料的改變并不影響界面展示,可以在這裡做判斷,優化渲染效率。

void componentWillUpdate(nextProps, nextState)
                

shouldComponentUpdate傳回true或者調用forceUpdate之後,componentWillUpdate會被調用。

void componentDidUpdate()
                

除了首次render之後調用componentDidMount,其它render結束之後都是調用componentDidUpdate。

componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以對應起來。差別在于,前者隻有在挂載的時候會被調用;而後者在以後的每次更新渲染之後都會被調用。

ReactElement render()
           

render是一個React元件所必不可少的核心函數(上面的其它函數都不是必須的)。記住,不要在render裡面修改state。

void componentWillUnmount()
                

元件被解除安裝的時候調用。一般在componentDidMount裡面注冊的事件需要在這裡删除。

更新方式

在react中,觸發render的有4條路徑。

以下假設shouldComponentUpdate都是按照預設傳回true的方式。

  1. 首次渲染Initial Render
  2. 調用this.setState (并不是一次setState會觸發一次render,React可能會合并操作,再一次性進行render)
  3. 父元件發生更新(一般就是props發生改變,但是就算props沒有改變或者父子元件之間沒有資料交換也會觸發render)
  4. 調用this.forceUpdate

下面是我對React元件四條更新路徑地總結:

React元件生命周期小結React 生命周期相關函數更新方式一個React元件生命周期的測試例子

React元件更新路徑.png

注意,如果在shouldComponentUpdate裡面傳回false可以提前退出更新路徑。

一個React元件生命周期的測試例子

代碼比較簡單,沒有邏輯,隻是在每個相關函數裡面alert一下。<h1>點選連結來試試這個例子。</h1>

源碼:

class LifeCycle extends React.Component {
    constructor(props) {
        super(props);
        alert("Initial render");
        alert("constructor");
        this.state = {str: "hello"};
    }

    componentWillMount() {
        alert("componentWillMount");
    }

    componentDidMount() {
        alert("componentDidMount");
    }

    componentWillReceiveProps(nextProps) {
        alert("componentWillReceiveProps");
    }

    shouldComponentUpdate() {
        alert("shouldComponentUpdate");
        return true;        // 記得要傳回true
    }

    componentWillUpdate() {
        alert("componentWillUpdate");
    }

    componentDidUpdate() {
        alert("componentDidUpdate");
    }

    componentWillUnmount() {
        alert("componentWillUnmount");
    }

    setTheState() {
        let s = "hello";
        if (this.state.str === s) {
            s = "HELLO";
        }
        this.setState({
            str: s
        });
    }

    forceItUpdate() {
        this.forceUpdate();
    }

    render() {
        alert("render");
        return(
            <div>
                <span>{"Props:"}<h2>{parseInt(this.props.num)}</h2></span>
                <br />
                <span>{"State:"}<h2>{this.state.str}</h2></span>
            </div>
        );
    }
}

class Container  extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            num: Math.random() * 
        };
    }

    propsChange() {
        this.setState({
            num: Math.random() * 
        });
    }

    setLifeCycleState() {
        this.refs.rLifeCycle.setTheState();
    }

    forceLifeCycleUpdate() {
        this.refs.rLifeCycle.forceItUpdate();
    }

    unmountLifeCycle() {
        // 這裡解除安裝父元件也會導緻解除安裝子元件
        React.unmountComponentAtNode(document.getElementById("container"));
    }

    parentForceUpdate() {
        this.forceUpdate();
    }

    render() {
        return (
            <div>
                <a href="javascript:;" className="weui_btn weui_btn_primary" onClick={this.propsChange.bind(this)}>propsChange</a>
                <a href="javascript:;" className="weui_btn weui_btn_primary" onClick={this.setLifeCycleState.bind(this)}>setState</a>
                <a href="javascript:;" className="weui_btn weui_btn_primary" onClick={this.forceLifeCycleUpdate.bind(this)}>forceUpdate</a>
                <a href="javascript:;" className="weui_btn weui_btn_primary" onClick={this.unmountLifeCycle.bind(this)}>unmount</a>
                <a href="javascript:;" className="weui_btn weui_btn_primary" onClick={this.parentForceUpdate.bind(this)}>parentForceUpdateWithoutChange</a>
                <LifeCycle ref="rLifeCycle" num={this.state.num}></LifeCycle>
            </div>
        );
    }
}

ReactDom.render(
    <Container></Container>,
    document.getElementById('container')
);
                

作者:linjinhe

連結:https://www.jianshu.com/p/4784216b8194

來源:簡書

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。