博客 / 詳情

返回

React(8)React組件的生命週期

前言

本篇文章我們來系統的講解React組件的生命週期。React隨着版本的不斷提升,組件的生命週期也在不斷地改版和升級。本篇文章以React 17為例,講解最新版React的組件生命週期,同時闡述各個生命週期所執行的生命週期函數。


一、React組件的生命週期

React 17將組件的生命週期分為以下三個階段:

  • 組件的掛載階段(Mounting)
  • 組件的更新階段(Updating)
  • 組件的卸載階段(Unmounting)

二、React組件的掛載階段

在React中,將組件第一次插入至DOM樹中渲染的過程稱之為“掛載”。掛載階段要完成組件狀態的初始化、創建API調用請求、啓動或停止計時器、操作已渲染的DOM、初始化第三方腳本庫等工作。React組件掛載階段涉及到以下四個生命週期函數。

  • constructor()
  • getDerivedStateFromProps()
  • render()
  • componentDimMount()

1、constructor()構造函數

從原理上來講,constructor()構造函數並不是一個生命週期函數,只是當組件掛載時,構造函數永遠是第一個被觸發的。構造函數的主要功能是初始化組件狀態,即為state區設置初始化數據。
構造函數的格式如下所示。

class Comp extends react.Component{
  constructor(props){
    super(props);
    this.state={
      // 初始化React組件狀態
    }
  }
} 

2、getDerivedStateFromProps()生命週期函數

該函數是一個靜態函數,使用時必須聲明static關鍵字,且不能在其內部使用this關鍵字。同時使用時有兩個參數:nextProps、prevState,分別用來表示父組件傳遞過來的參數對象和組件的state區數據對象。該生命週期函數在使用時有如下規定。

  • 組件必須在constructor()構造函數中設置state區,否則該函數會報錯。
  • 該生命週期函數必須返回一個對象,或者返回null。

從這個生命週期函數的名字中就可以看出,它的功能是從props中獲取state,即利用父組件傳遞過來的props屬性來更新state數據。

例1:父組件調用子組件,並向Comp傳遞title和content兩個參數。

父組件核心代碼:

<Comp title="組件掛載" content="將組件第一次插入至DOM樹中渲染"></Comp> 

子組件代碼:

class Comp extends React.Component{
  constructor(props){
    super(props);
    this.state={
      ca:15,
      cb:20
    }
    console.log(this.state);
  }
  static getDerviedStateFromProps(nextProps,prevState){
    console.log(nextProps);
    console.log(prevState);
    const {title,content} = nextProps;
    return {
      title,content
    }
  }
} 

在上述代碼中,組件Comp掛載階段,先執行構造函數constructor(),再執行靜態函數getDerviedStateFromProps()。所以在構造函數中輸出this.state,結果為:{ca:15,cb:20}。

靜態函數getDerviedStateFromProps()中nextProps參數是父組件向子組件傳遞的數據構成的對象,所以輸出nextProps的結果為:{title:“組件掛載”,content:“將組件第一次插入至DOM樹中渲染”}。

靜態函數getDerviedStateFromProps()中返回的對象都是要加入到組件的state狀態中的,所以父組件向子組件傳遞的title數據和content數據也會變為state狀態區中的一部分。

3、render()渲染函數

render()渲染函數是React組件的必備函數,沒有該函數React組件會報錯。該函數用來返回使用JSX語法實現的組件內容,包括HTML標記對和JavaScript業務流程。在例1中,如果在render()函數中輸出this.state,因為getDerviedStateFromProps()函數在render()函數之前執行,所以此時輸出的結果為:{ca:15,cb:20,title:“組件掛載”, content:“將組件第一次插入至DOM樹中渲染”}。

4、componentDidMount()生命週期函數

該函數是組件掛載階段最後一個執行的生命週期函數,會在組件掛載成功且渲染完畢之後觸發。項目開發過程中,多在該函數中調取API數據,例如使用Fetch、Axios技術從後台獲取組件使用的數據。

三、React組件的更新階段

在React中,將組件重新渲染的過程稱之為“更新”。當組件的state數據發生變化或從父組件接收到新的屬性時進入到組件的更新階段,即調用this.setState()方法時,組件會啓動更新階段。React組件更新階段涉及到以下五個生命週期函數。

  • getDerviedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

首先,要重點聲明。上述函數都是在組件更新時觸發的生命週期函數,即一旦執行了this.state()方法,上述函數就會依次執行一遍。也就是説,如果在上述函數中調用了this.state()方法,將會使更新生命週期引發無限遞歸循環,從而導致堆棧溢出。因此上述函數中不得調用this.state()方法。render()函數中元素的事件函數除外,因為事件函數雖然書寫在render()函數內部,但是並不自動執行,因此不會導致堆棧溢出。

1、shouldComponentUpdate()生命週期函數

該生命週期函數有兩個參數:nextProps、prevState,分別用來表示父組件傳遞過來的參數對象和組件的state區數據對象。
該生命週期函數被稱為更新階段的“門衞”,在使用時必須返回一個邏輯值,以表示後面的更新生命週期函數是否繼續執行。

  • 返回true,表示繼續執行組件的更新生命週期函數。
  • 返回false,表示不再繼續執行組件的更新生命週期函數。

這裏需要注意,該生命週期函數返回false,只表示不再繼續執行後面的生命週期函數,觸發更新聲明週期啓動的this.setState()方法依然會成功執行。

例2:當更新state區中的title數據時,判斷父組件傳遞的title是否與更新後的title一致,如一致就停止執行生命週期過程;如不一致則繼續執行生命週期過程。
class Comp extends Component {
  constructor(props){
    super(props);
    this.state={
      ca:15,
      cb:20
    };
  }
  shouldComponentUpdate(nextProps,prevState){
    if(nextProps.title!==prevState.title){
      return true;
    }
    return false;
  }
  btnClick(){
    this.setState({
      title:"你好"
    })
  }
  render() {
    console.log("Render函數");
    console.log(this.state);
    return (
      <Fragment>
        我是Comp組件
        <p><button onClick={()=>this.btnClick()}>單擊我</button></p>
      </Fragment>
    );
  }
} 

2、getSnapshotBeforeUpdate()生命週期函數

該生命週期函數在組件的更新階段,在render()函數之後,組件DOM渲染之前觸發。具備以下兩個參數。

  • prevProps:依然表示父組件向子組件傳遞的數據。
  • prevState:依然表示state區中的數據。

該生命週期函數在使用時有如下兩個規定:

  • 必須配合componentDidUpdate()生命週期函數共同使用。
  • 必須返回一個值,該值將作為componentDidUpdate()生命週期函數的第三個參數。

3、componentDidUpdate()生命週期函數

該生命週期函數在組件更新完成後觸發,其語法格式如下所示。
componentDidUpdate(prevProps,prevState,snapshot){}

四、React組件的卸載階段

在React中,從DOM樹中刪除組件的過程稱之為“卸載”。該生命週期只有一個生命週期函數。

  • componentWillUnmount()

可以在該生命週期函數中清除timer計時器以及在componentDidMount()生命週期函數中聲明的變量。


總結

本文是React系列教程的第八篇文章,主要為大家講解了React 17中組件的生命週期與各個生命週期的函數。整體來説,生命週期函數的執行可以用下圖來進行説明。
在這裏插入圖片描述

關於作者

小海前端,具有18年Web項目開發和前後台培訓經驗,在前端領域著有較為系統的培訓教材,對Vue.js、微信小程序開發、uniApp、React等全棧開發領域都有較為深的造詣。入住Segmentfault,希望能夠更多的結識Web開發領域的同仁,將Web開發大力的進行普及。同時也願意與大家進行深入的技術研討和商業合作。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.