React 生命周期
前言
學習React,生命周期很重要,我們了解完生命周期的各個元件,對寫高性能元件會有很大的幫助.
Ract生命周期
React 生命周期分為三種狀态 1. 初始化 2.更新 3.銷毀
- 初始化
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的方式。
- 首次渲染Initial Render
- 調用this.setState (并不是一次setState會觸發一次render,React可能會合并操作,再一次性進行render)
- 父元件發生更新(一般就是props發生改變,但是就算props沒有改變或者父子元件之間沒有資料交換也會觸發render)
- 調用this.forceUpdate
下面是我對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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。