淺析React組件的生命週期(代碼解析)

來源:互聯網
上載者:User
本篇文章給大家帶來的內容是關於淺析React組件的生命週期(代碼解析),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所協助。

整個 React 生命週期有3個階段:建立、更新、卸載,每個階段有對應的工作和方法,我們可以看下面這個經典的圖研究一下:

第一階段

這是虛擬 DOM 建立的階段,會依次執行 5 個方法,這 5 個方法中除了 render 方法,其餘四個方法在整個生命週期中只調用 1 次,而且一定會調用 1 次:

  • getDefaultProps()

這個方法在組件執行個體建立前,也就是建構函式執行前執行,擷取父組件傳來的參數,你可以在這裡編輯參數並返回新的參數作為 props

  • getInitalState()

組件建立的一開始會調用這個方法初始化組件的 state

  • componentWillMount()

在組件 render 之前執行該方法,可用來修改 state。React 先調用父組件的這個函數,再調用子組件的這個函數

  • render()

開始組件渲染函數,返回一個只有一個根節點的虛擬 DOM。該函數中不能同步的修改組件的狀態(state)。

  • componentDidMount()

在 render 渲染之後,通知群組件已經載入完成。React 先調用子組件的這個函數,再調用父組件的這個函數。從這個函數開始,該組件就可以和其他架構互動了。比如設定計時器或者發起網路請求。

第二階段

此時該組件已經進入了穩定運行階段,這個階段組件可以處理使用者互動,或者接收事件更新介面。以下方法在整個生命週期中可以執行很多次,也可以一次也不執行。

  • componentWillReceiveProps()

當父容器中對應的參數改變將會調用子組件的該函數。新的 props 將會作為參數傳遞進來,老的 props 可以根據 this.props 來擷取。我們可以在該函數中對state作一些處理。並且在該函數中更新 state 不會發生二次渲染

  • shouldComponentUpdate()

該函數傳遞過來兩個參數,新的 state 和新的 props。state 和 props 的改變都會調到該函數。該函數主要對傳遞過來的 nextProps 和 nextState 作判斷。如果返回 true 則重新渲染(預設都是返回 true),如果返回 false 則不重新渲染。在某些特定條件下,我們可以根據傳遞過來的 props 和 state 來選擇更新或者不更新,從而提高效率。

  • componentWillUpdate()

與 componentWillMount 方法類似,在 render 渲染之前被調用。組件上會接收到新的 props 或者 state。這個函數調用之後,就會把 nextProps 和 nextState 分別設定到 this.props 和 this.state 中。

  • componentDidUpdate()

與 componentDidMount 方法類似,在 render 渲染之後被調用,真實 DOM 產生之後調用該函數。傳遞過來的參數是之前的 props 和 state。

第三階段

這就是消亡的階段,主要進行記憶體的清理和釋放的工作。這個階段只有一個方法,該方法在整個生命週期內調用且僅調用一次。

  • componentWillUnmount()

當組件要被從介面上移除的時候,就會調用 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'));
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.