React組件的生命周期詳細描述
一、什麼是生命周期
組件的生命周期就是React的工作過程,就好比人有生老病死,自然界有日月更替,每個組件在網頁中也會有被創建、更新和刪除,如同有生命的機體一樣。
React組件的生命周期可以分為三個過程
- 裝載(掛載)過程(mount):就是組件第一次在DOM樹中渲染的過程。
- 更新過程(update):組件被重新渲染的過程。
- 卸載過程(unmount):組件從DOM中被移除的過程。
二、裝載過程
依次調用如下函數constructor、getInitialState、getDefaultProps、componentWillMount、render、componentDidMount。
1、constructor
就是ES6裡的構造函數,創建一個組件類的實例,在這一過程中要進行兩步操作:初始化state,綁定成員函數的this環境。
2、render
render是React組件中最為重要的一個函數。這是react中唯一不可忽略的函數,在render函數中,隻能有一個父元素。render函數是一個純函數,它並不進行實際上的渲染動作,它隻是一個JSX描述的結構,最終是由React來進行渲染過程,render函數中不應該有任何操作,對頁面的描述完全取決於this.state和this.props的返回結果,不能在render調用this.setState。
- 有一個公式總結的非常形象 UI=render(data)
3、componentWillMount和componentDidMount
這兩個函數分別在render前後執行,由於這一過程通常隻能在瀏覽器端調用,所以我們在這裡獲取異步數據,而且在componentDidMount調用的時候,組件已經被裝載到DOM樹上瞭。
三、更新過程
簡單來說就是props和state被修改的過程,依次調用componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate。
1、componentWillReceiveProps(nextProps)
並不是隻有在props發生改變的時候才會被調用,實際上隻要是父組件的render函數被調用,render裡面被渲染的子組件就會被更新,不管父組件傳給子組件的props有沒有被改變,都會觸發子組件的componentWillReceiveProps過程,但是,this.setState方法的觸發過程不會調用這個函數,因為這個函數適合根據新的props的值來計算出是不是要更新內部狀態的state。
2、shouldComponentUpdate(nextProps, nextState)
這個函數的重要性,僅次於render,render函數決定瞭該渲染什麼,而shouldComponentUpdate決定瞭不需要渲染什麼,都需要返回函數,這一過程可以提高性能,忽略掉沒有必要重新渲染的過程。
3、componentWillUpdate和componentDidUpdate
和裝載過程不同,這裡的componentDidUpdate,既可以在瀏覽器端執行,也可以在服務器端執行
4、觸發render
在react中,觸發render的有4條路徑。
以下假設shouldComponentUpdate都是按照默認返回true的方式:
(1) 首次渲染Initial Render。
(2) 調用this.setState (並不是一次setState會觸發一次render,React可能會合並操作,再一次性進行render)。
(3) 父組件發生更新(一般就是props發生改變,但是就算props沒有改變或者父子組件之間沒有數據交換也會觸發render)。
(4) 調用this.forceUpdate。
註意:如果在shouldComponentUpdate裡面返回false可以提前退出更新路徑。
四、卸載過程
實際中很少用到,這裡隻有一個componentWillUnmount,一般在componentDidMount裡面註冊的事件需要在這裡刪除。
五、生命周期流程
1、第一次初始化渲染顯示: ReactDOM.render()
constructor():
創建對象初始化 statecomponentWillMount() :
將要插入回調render() :
用於插入虛擬 DOM 回調componentDidMount() :
已經插入回調
2、每次更新 state: this.setState()
componentWillUpdate()
: 將要更新回調render()
: 更新(重新渲染)componentDidUpdate()
: 已經更新回調
3、移除組件: ReactDOM.unmountComponentAtNode(containerDom)
- componentWillUnmount() : 組件將要被移除回調
六、示例
<div id='container'></div> <script type="text/babel"> 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() { // 這裡卸載父組件也會導致卸載子組件 ReactDOM.unmountComponentAtNode(document.getElementById("container")); } parentForceUpdate() { this.forceUpdate(); } render() { return ( <div> <a href="javascript:;" onClick={this.propsChange.bind(this)}>propsChange</a> <a href="javascript:;" onClick={this.setLifeCycleState.bind(this)}>setState</a> <a href="javascript:;" onClick={this.forceLifeCycleUpdate.bind(this)}>forceUpdate</a> <a href="javascript:;" onClick={this.unmountLifeCycle.bind(this)}>unmount</a> <a href="javascript:;" onClick={this.parentForceUpdate.bind(this)}>parentForceUpdateWithoutChange</a> <LifeCycle ref="rLifeCycle" num={this.state.num}></LifeCycle> </div> ); } } ReactDOM.render( <Container></Container>, document.getElementById('container') ); </script>
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!