一、概念
在組件創建、組件屬性更新、組件被銷毀的過程中,總是伴隨著各種各樣的函數執行,這些在組件特定時期,被觸發執行的函數,統稱為組件的生命周期函數。
二、組件生命周期的三個階段
1、加載階段(Mounting):組件初始化時執行,最顯著的特點是該階段的生命周期函數在組件的一輩子中只執行一次
2、更新階段(Updating):屬性(props)和狀態(state)發生變化時執行,根據組件pros和state的改變,有選擇性的觸發0次或多次
3、卸載階段(Unmounting):組件對象銷毀時執行,一輩子只執行一次
三、生命周期圖
四、生命周期三個階段詳解
1、加載階段(Mounting,涉及6個鉤子函數)
(1)constructor()——構造函數,在加載時(創建組件時)調用一次,可以初始化state
(2)getDefaultProps()——設置默認的props,也可以用defaultProps設置組件的默認屬性
(3)getInitialState()——初始化state,可以直接在constuctor中定義this state
(4)componentWillMount()——組件加載之前調用,以后組件更新不調用,整個生命周期只調用一次,此時可以修改state,即調用setState,則本次的render函數可以看到更新后的state
(5)render()——react最重要的步驟,創建虛擬DOM,進行diff算法,更新DOM樹都在此階段進行,切忌不要再render里邊修改state
(6)componentDidMount()——組件渲染之后調用,只調用一次,此時子組件也掛載好了,可以使用refs
2、更新階段(Updating,涉及5個鉤子函數)
(1)componentWillReceiveProps(nextProps)——組件加載時不調用,組件接收新的props時調用,父組件發生render的時候子組件就會調用(不管props有沒有更新,也不管父子組件之間有沒有數據交換)
(2)shouldComponentUpdate(nextProps, nextState)——組件接收到新的props或者state時調用,return true就會更新DOM(使用diff算法更新),return false可以阻止更新(不調用render),可以優化渲染效率
(3)componentWillUpdate(nextProps, nextState)——組件加載時不調用,只有在組件將要更新時才調用,此時可以修改state
(4)render()——react最重要的步驟,創建虛擬DOM,進行diff算法,更新DOM樹都在此階段進行
(5)componentDidUpdate()——組件加載時不調用,組件更新完成后調用,除了首次render之后調用componentDidMount(),其他render結束之后都是調用componentDidUpdate()
3、卸載階段(Unmounting,涉及1個鉤子函數)
(1)componentWillUnmount()——組件被卸載時調用,只調用一次,一般在componentDidMount里面注冊的事件需要在這里刪除
五、react組件更新方式:react中觸發render有4種方式
1、首次渲染initial render
2、調用this.setState(但并不是一次setState就會觸發一次render,React可能會合并操作,再一次性進行render)
3、父組件發生更新(一般就是props發生改變,但是就算props沒有改變或者父子組件之間沒有數據交換也會觸發render)
4、調用this.forceUpdate
六、完整例子
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() * 100
};
}
propsChange() {
this.setState({
num: Math.random() * 100
});
}
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')
);