本篇文章給大家帶來的內容是關於淺析React組件的生命週期(代碼解析),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所協助。
整個 React 生命週期有3個階段:建立、更新、卸載,每個階段有對應的工作和方法,我們可以看下面這個經典的圖研究一下:
第一階段
這是虛擬 DOM 建立的階段,會依次執行 5 個方法,這 5 個方法中除了 render 方法,其餘四個方法在整個生命週期中只調用 1 次,而且一定會調用 1 次:
這個方法在組件執行個體建立前,也就是建構函式執行前執行,擷取父組件傳來的參數,你可以在這裡編輯參數並返回新的參數作為 props
組件建立的一開始會調用這個方法初始化組件的 state
在組件 render 之前執行該方法,可用來修改 state。React 先調用父組件的這個函數,再調用子組件的這個函數
開始組件渲染函數,返回一個只有一個根節點的虛擬 DOM。該函數中不能同步的修改組件的狀態(state)。
在 render 渲染之後,通知群組件已經載入完成。React 先調用子組件的這個函數,再調用父組件的這個函數。從這個函數開始,該組件就可以和其他架構互動了。比如設定計時器或者發起網路請求。
第二階段
此時該組件已經進入了穩定運行階段,這個階段組件可以處理使用者互動,或者接收事件更新介面。以下方法在整個生命週期中可以執行很多次,也可以一次也不執行。
當父容器中對應的參數改變將會調用子組件的該函數。新的 props 將會作為參數傳遞進來,老的 props 可以根據 this.props 來擷取。我們可以在該函數中對state作一些處理。並且在該函數中更新 state 不會發生二次渲染
該函數傳遞過來兩個參數,新的 state 和新的 props。state 和 props 的改變都會調到該函數。該函數主要對傳遞過來的 nextProps 和 nextState 作判斷。如果返回 true 則重新渲染(預設都是返回 true),如果返回 false 則不重新渲染。在某些特定條件下,我們可以根據傳遞過來的 props 和 state 來選擇更新或者不更新,從而提高效率。
與 componentWillMount 方法類似,在 render 渲染之前被調用。組件上會接收到新的 props 或者 state。這個函數調用之後,就會把 nextProps 和 nextState 分別設定到 this.props 和 this.state 中。
與 componentDidMount 方法類似,在 render 渲染之後被調用,真實 DOM 產生之後調用該函數。傳遞過來的參數是之前的 props 和 state。
第三階段
這就是消亡的階段,主要進行記憶體的清理和釋放的工作。這個階段只有一個方法,該方法在整個生命週期內調用且僅調用一次。
當組件要被從介面上移除的時候,就會調用 componentWillUnmount。在這裡進行一些相關的銷毀操作,比如撤銷定時器,事件監聽等等。
觸發 render 的幾種情況
這裡我們僅考慮 shouldComponentUpdate 沒有被修改,始終返回的是 true
首次渲染,即 Initial Render
調用this.setState (不是每次調用 setState 都會觸發,react 會最佳化,比如 antd 的 input 組件)
父組件發生更新,通常是修改的子組件的 props
如果父組件觸發了 render, 子組件當然也會相應觸發 render
調用 this.forceUpdate()
一個簡單的樣本
import React from 'react';import ReactDOM from 'react-dom';import style from './font.css';import './index.less';class Parent extends React.Component{ constructor(props) { super(props); this.state = { willRender: true, prop: 1 }; } render(){ return ( <div> <button onClick={()=>{this.setState({prop: 10})}}>changePropsFromParent</button> { this.state.willRender && <Child fromParent={this.state.prop}/> } <button onClick={()=>{this.setState({willRender: false})}}>UnmountChild</button> </div> ); }}class Child extends React.Component { constructor(props) { super(props); this.state = { curr: 0 }; } getDefaultProps(){ console.log('getDefaultProps'); } getInitalState(){ console.log('getInitalState'); } componentWillMount(){ console.log('componentWillMount'); } componentDidMount(){ console.log('componentDidMount'); } componentWillReceiveProps(){ console.log('componentWillReceiveProps'); } shouldComponentUpdate(){ console.log('shouldComponentUpdate'); return true; } componentWillUpdate(){ console.log('componentWillUpdate'); } componentDidUpdate(){ console.log('componentDidUpdate'); } componentWillUnmount(){ console.log('componentWillUnmount'); } render() { console.log('render') return ( <div> <button onClick={()=>this.setState({curr:2})}>setState</button> <button onClick={()=>{this.forceUpdate();}}>forceUpdate</button> </div> ); }}ReactDOM.render( <Parent />, document.getElementById('root'));