React學習(8)-React中組件的生命週期

前言

爲了進一步瞭解React的工做過程,已經曉得了怎麼編寫React組件,知道了React的數據流,那麼是時候學習React組件的生命週期了,每一個組件都包含生命週期方法,生命週期如同四季更替,一我的的生,老,病,死.在每一個特殊的年齡階段,作着不一樣的事情javascript

在React編寫組件中,一樣,每一個組件在網頁中都有被建立,更新,刪除這麼一過程,就像有機的生命體同樣java

理解生命週期函數對於編寫React組件代碼是很是重要的react

若是你不清楚生命週期,以及生命週期的應用場景,那麼本篇就是你想要知道的瀏覽器

戳該連接,閱讀體驗更好,React中組件的生命週期bash

生命週期(鉤子)函數

定義: 在特定的階段,可以自動執行的函數(方法)服務器

在前面的JSX學習中,一個React元素渲染到頁面當中,本質上是經過底層的React.CreateElement的一個方法實現的,它是一個javascript對象,將虛擬DOM轉化爲真實的DOM,最後經過ReactDOM.render()方法將真實的DOM渲染掛載到對應的頁面位置上網絡

一個組件的渲染,經歷瞭如下幾個過程:能夠對照這個生命週期圖譜的 dom

完整生命週期圖.png

  • 組件的裝載(Mount):React組件第一次在DOM樹中渲染的過程
    • componentWillMount:組件即將被掛載,在Render方法以前調用:
    • 應用場景: 經常使用於組件的啓動工做,例如:Ajax數據的獲取,定時器的啓動,相似Render函數的前哨,調用setState修改狀態也不會引發從新繪製,這個時候沒有任何渲染,須要注意的是,它能夠在服務器端被調用,也能夠在瀏覽器端調用
  • componentDidMount:組件被加載完以後調用,也就是render函數執行以後調用,至關於render函數的後衛,當這個生命週期執行時,render函數會引起渲染,組件從新掛載到DOM樹上,注意它只能在瀏覽器端調用,在服務器端使用React的時候不會調用,裝載是將組件渲染,而且構造DOM元素,而後塞入頁面的過程,這個狀態是不可能在服務器端完成的,服務器端不可能產生DOM樹的 應用場景:咱們每每在這個生命週期內進行Ajax的獲取,填充組件的內容,由於在componentDidMount被調用時,組件已經掛載到DOM樹上了,而每每若須要結合第三方庫的使用,例如:JQ等,也是放到這個生命週期函數中進行處理的
  • getSnapshotBeforeUpdate(prevProps, prevState): 使用場景:該函數在最終render結果提交到DOM以前被調用,記錄DOM刷新前的特性,如:滾動位置 注意:該函數的返回值會做爲參數傳遞給ComponentDidUpdate
  • componentWillUnmount: 當組件對應的 DOM 元素從頁面中刪除以前調用
  • 組件的更新(update): 當組件被從新渲染的過程(state與props發生改變都會引發渲染)
    • componentWillReceiveProps
    • shouldComponentUpdate
    • componentWillUpdate
    • componentDidUpdate
  • 組件的卸載(unmount): 組件從DOM中刪除的過程
    • componentWillUnmount: 組件從頁面銷燬時,會觸發該函數,當須要對數據進行清理時,例如定時器的清理,放到該函數裏面去作

三種不一樣的過程,React庫會依次調用組件的一些成員函數(生命週期函數)異步

裝載過程

當組件第一次被渲染的時候,會依次的調用以下生命週期函數函數

  • constructor:構造器函數
  • getDerivedStateFromProps(props,state):

使用場景:當組件內部的state變化依賴於props時,調用該生命週期函數 注意:不要過分使用該函數,若是你的操做依賴於props的更改並有反作用,最好放到componentDidUpdate中

  • componentWillMount:組件掛載開始以前調用,也就是render函數以前被自動調用,在React16.3版本以後不該該使用,因爲該函數在Render函數以前調用,所以使用同步的setState方法不會觸發額外的render處理

它也只會在初始化的時候調用一次,因此this壞境的綁定放在這裏面也是能夠的,可是最好是放在constructor構造器函數裏面,若是是處理帶有後續異步操做或者有反作用的訂閱事件處理,例如:Ajax數據獲取,則放到componentDidMount中

  • render:組件的渲染,插入到DOM元素中,
  • componentDidMount:組件掛載完以後調用,也就是在render函數以後調用,DOM已經插入到頁面中了的,能夠在這裏使用refs

constructor:構造器函數

constructor(ptops) {
    super(props);  // 必定要調用super,而且接收props參數,不然該組件的實例方法沒法獲取到外部的props值
}
複製代碼

至於constructor在上節當中已經說起過,並非每一個組件都須要定義constructor構造器函數,函數式(無狀態)組件就不須要定義構造函數

通常使用constructor構造函數有以下兩種狀況

  • 組件內部初始化state,由於生命週期內的任何函數均可能要訪問state,取它的值,進行相應的邏輯處理,它是該組件一個私有的對象變量
  • 在對JSX元素上綁定事件監聽處理函數時,也就是組件內部成員函數(方法)this壞境的綁定,由於在Es6中類的成員方法在執行時this並不會和類的實例化自己自動的綁定,你須要手動bind的方式進行綁定

爲了方便調用,在構造函數中,this就是當前組件的實例,每每在構造函數中將組件實例下的成員方法綁定this爲當前的實例對象

constructor(props){
  super(props);
}
// 事件監聽處理函數,this壞境的綁定
this.handleBtnClick = this.handleBtnCLick.bind(this);
this.handleInputChange = this.handleInputChange.bind(this)
複製代碼

在執行了constructor構造器函數後,執行componentWillMount方法,而後在執行render方法,執行完render方法後,在執行componentDidMount方法,整個裝載過程就結束了的

固然這其中的一個componentWillUnmount方法是在組件銷燬前進行觸發,也就是刪除DOM元素以前調用,這個經常使用於當組件從頁面刪除銷燬時,作一些數據清理的時候能用得上,例如定時器的清理,取消網絡請求,在該生命週期函數內,不該該調用setState函數,由於該組件銷燬後,將不會被從新渲染

具體的實例代碼以下所示:

import React, { Fragment, Component } from 'react';      
import ReactDOM from 'react-dom';

class LifeCycle extends Component {
  constructor(props){
    super(props);
    console.log("1-constructor函數被調用執行");
    this.state = {
      isShow: true
    }

    this.handleBtnClick = this.handleBtnClick.bind(this);
    
  }

  componentWillMount(){
    console.log("2-componentWillMount函數已執行,組件掛載以前,在render方法以前調用", this.state.isShow);
  }

  componentDidMount() {
    console.log("4-componentDidMount函數已執行,組件掛載完以後,DOM元素已經插入到頁面後調用");
  }

  render(){
    console.log("3-render函數執行");
    return (
      <Fragment>
          <div>
               { this.state.isShow? <Text />:""}
               <button onClick={ this.handleBtnClick }>更改</button>
          </div>
      </Fragment>
    );
  }

  handleBtnClick(){
    this.setState({
      isShow:!this.state.isShow 
    })
  }

  

}

class Text extends Component {
  componentWillUnmount(){
    console.log("componentWillUnmount函數已執行,組件從頁面中移除以前調用,Text組件移除");
  }
  render(){
    console.log("Text組件被渲染");
    return (
       <h1>itclanCoder</h1>
    );
  }
} 

const container = document.getElementById('root');

ReactDOM.render(<LifeCycle   />, container);
複製代碼

效果以下所示:

組件的裝載過程.gif

你們能夠自行將這些生命週期函數放到組件內部當中,進行測試的,看每一個生命週期執行的順序就一目瞭然了的

說完了組件的裝載,那麼接下來就是組件的更新了

組件的更新

當props或者state發生改變的時候,就會引發render函數的渲染,也就是會引起組件的更新,它與組件的裝載同樣,會觸發一些生命週期函數

更新組件時:生命週期函數執行的順序

  • componentWillReceiveProps(nextProps,nextState):只要父組件的render函數被調用,在render函數裏面被渲染的子組件就會經歷更新的過程,不管父組件傳給子組件的props有沒有改變,都會觸發子組件的componentWillReceiveProps函數

你能夠理解爲,第一次渲染時,父組件的componentWillReceiveProps函數不會被執行,若是是第二次渲染時,已經存在於父組件中,則該componentWillReceiveProps纔會執行

注意:在掛載過程當中,React不會針對初始props調用此方法,經過觸發setState方法更新過程不會調用這個函數,這是由於這個函數適合根據新的props值(也就是nextProps)來計算出是否是要更新內部狀態state

應用場景:當你但願只有在接收新的props時作一些邏輯時,props改變須要相應改變內部state狀態時,則使用componentWillReceiveProps,好比:根據父組件傳入的數據初始化或重置組件內部的某些state狀態

  • shouldComponentUpdate:它決定一個組件何時不須要被渲染,在組件更新過程當中,Render函數以前調用執行,它同Render函數同樣,要求有返回結果的函數

返回一個boolean值,告訴React庫這個組件在此次更新過程是否要繼續,若是該函數返回true,那麼繼續更新,調用render函數,反之,若函數返回false,那麼馬上中止更新過程,便不會執行render函數了的

這個函數是提升React的性能的,若是發現不必的渲染,那就乾脆不用渲染了的,這個shouldComponentUpdate就能夠作到

注意: forceUpdate不會觸發該函數,也可使用PureComponent替代該函數,該函數作了內部的優化

// nextProps表示的是接下來個人props值會樣,nextState表示的是個人state會變成什麼樣
shouldComponentUpdate(nextProps, nextState)
  if(nextProps.props屬性 !== this.props.props屬性 || nextState.state屬性 !== this.state.state屬性)
  return true;    
}else{
  return false
}
複製代碼
  • componentWillUpdate: 組件即將更新時調用,在Render函數以前調用

注意: 不要在該函數中經過this.setState再次改變state,若是須要,則在componentWillReceiveProps函數中改變

  • render:決定該組件UI渲染結果,返回的結果用於構造DOM對象

注意:不能在render函數中調用setState,若是在shouldComponentUpdate返回false,則render函數不會被調用

  • componentDidUpdate:組件更新完以後執行,有兩個參數prevProps和prevState,不管是父組件props的修改仍是狀態的更改都會觸發該方法

應用場景:若是但願不管props更改仍是組件內的狀態更改都能觸發一些邏輯,則可使用componentDidUpdate,進行業務處理,發送網絡請求

注意:在處理業務或發送網絡請求時,必定要作好條件比較,不然容易形成死循環

組件的卸載

React組件從頁面中移除時,在卸載的過程當中,只涉及一個生命週期函數componentWillUnmount,因爲該函數在組件刪除以前會被調用,因此該函數適合作一些清理性的工做

應用場景: 清理無效的timer,取消未完成的網絡請求,清理已註冊的訂閱

注意:在這裏使用setState時無效的

固然對於React的生命週期,不一樣的版本,官方對它作了一些優化和改動,這裏介紹的是React Version 16.2.0版本的,生命週期過程圖以下所示

React Version16.2.png

若是是最新的,在React17.0版本中,生命週期函數以下所示

React17.0生命週期過程圖.png

總結

本文主要講解了React的生命週期,只要理解了生命週期的圖譜,生命週期也就差很少了的,在constructor構造器中初始化工做,componentWillMount在組件即將掛載以前執行調用,經常使用於組件的啓動工做,例如:Ajax數據的獲取,定時器的啓動

固然數據的請求最好放在componentDidMount函數中,而當props或者state發生改變時,會引發組件的渲染,也就是組件的更新,只要父組件的render函數被渲染了,就會觸發子組件的componentWillReceiveProps,而當shouldComponentUpdate的函數返回true時,則render函數會渲染,要是返回false時,則render函數不會渲染

當組件從頁面中移除時,在卸載以前會觸發componentWillUnmount函數,該函數經常用於組件銷燬時調用,清理無效的定時器timer,取消未完成的網絡(Ajax)請求,清理已註冊的訂閱

相關文章
相關標籤/搜索