React的生命周期


這周開始學習React的生命周期。

React的生命周期從廣義上分為三個階段:掛載、渲染、卸載

因此可以把React的生命周期分為兩類:掛載卸載過程和更新過程。
React的生命周期圖:

React生命周期圖

1. 掛載卸載過程

1.1.constructor()

constructor()中完成了React數(shù)據(jù)的初始化,它接受兩個參數(shù):props和context,當想在函數(shù)內(nèi)部使用這兩個參數(shù)時,需使用super()傳入這兩個參數(shù)。
注意:只要使用了constructor()就必須寫super(),否則會導致this指向錯誤。

1.2.componentWillMount()

componentWillMount()一般用的比較少,它更多的是在服務端渲染時使用。它代表的過程是組件已經(jīng)經(jīng)歷了constructor()初始化數(shù)據(jù)后,但是還未渲染DOM時。

1.3.componentDidMount()

組件第一次渲染完成,此時dom節(jié)點已經(jīng)生成,可以在這里調(diào)用ajax請求,返回數(shù)據(jù)setState后組件會重新渲染

1.4.componentWillUnmount ()

在此處完成組件的卸載和數(shù)據(jù)的銷毀。

  1. clear你在組建中所有的setTimeout,setInterval
  2. 移除所有組建中的監(jiān)聽 removeEventListener
  3. 有時候我們會碰到這個warning:
Can only update a mounted or mounting component. This usually      means you called setState() on an unmounted component. This is a   no-op. Please check the code for the undefined component.

原因:因為你在組件中的ajax請求返回setState,而你組件銷毀的時候,請求還未完成,因此會報warning
解決方法:

componentDidMount() {
    this.isMount === true
    axios.post().then((res) => {
    this.isMount && this.setState({   // 增加條件ismount為true時
      aaa:res
    })
})
}
componentWillUnmount() {
    this.isMount === false
}

2. 更新過程

2.1. componentWillReceiveProps (nextProps)

  1. 在接受父組件改變后的props需要重新渲染組件時用到的比較多
  2. 接受一個參數(shù)nextProps
  3. 通過對比nextProps和this.props,將nextProps的state為當前組件的state,從而重新渲染組件
  componentWillReceiveProps (nextProps) {
    nextProps.openNotice !== this.props.openNotice&&this.setState({
        openNotice:nextProps.openNotice
    },() => {
      console.log(this.state.openNotice:nextProps)
      //將state更新為nextProps,在setState的第二個參數(shù)(回調(diào))可以打         印出新的state
  })
}

2.2.shouldComponentUpdate(nextProps,nextState)

  1. 主要用于性能優(yōu)化(部分更新)
  2. 唯一用于控制組件重新渲染的生命周期,由于在react中,setState以后,state發(fā)生變化,組件會進入重新渲染的流程,在這里return false可以阻止組件的更新
  3. 因為react父組件的重新渲染會導致其所有子組件的重新渲染,這個時候其實我們是不需要所有子組件都跟著重新渲染的,因此需要在子組件的該生命周期中做判斷

2.3.componentWillUpdate (nextProps,nextState)

shouldComponentUpdate返回true以后,組件進入重新渲染的流程,進入componentWillUpdate,這里同樣可以拿到nextProps和nextState。

2.4.componentDidUpdate(prevProps,prevState)

組件更新完畢后,react只會在第一次初始化成功會進入componentDidmount,之后每次重新渲染后都會進入這個生命周期,這里可以拿到prevProps和prevState,即更新前的props和state。

2.5.render()

render函數(shù)會插入jsx生成的dom結構,react會生成一份虛擬dom樹,在每一次組件更新時,在此react會通過其diff算法比較更新前后的新舊DOM樹,比較以后,找到最小的有差異的DOM節(jié)點,并重新渲染。

3. React新增的生命周期(個人補充)

React新增生命周期

3.1. getDerivedStateFromProps(nextProps, prevState)

代替componentWillReceiveProps()。
老版本中的componentWillReceiveProps()方法判斷前后兩個 props 是否相同,如果不同再將新的 props 更新到相應的 state 上去。這樣做一來會破壞 state 數(shù)據(jù)的單一數(shù)據(jù)源,導致組件狀態(tài)變得不可預測,另一方面也會增加組件的重繪次數(shù)。
舉個例子:

// before
componentWillReceiveProps(nextProps) {
  if (nextProps.isLogin !== this.props.isLogin) {
    this.setState({ 
      isLogin: nextProps.isLogin,   
    });
  }
  if (nextProps.isLogin) {
    this.handleClose();
  }
}

// after
static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.isLogin !== prevState.isLogin) {
    return {
      isLogin: nextProps.isLogin,
    };
  }
  return null;
}

componentDidUpdate(prevProps, prevState) {
  if (!prevState.isLogin && this.props.isLogin) {
    this.handleClose();
  }
}

這兩者最大的不同就是:
在 componentWillReceiveProps 中,我們一般會做以下兩件事,一是根據(jù) props 來更新 state,二是觸發(fā)一些回調(diào),如動畫或頁面跳轉等。

  1. 在老版本的 React 中,這兩件事我們都需要在 componentWillReceiveProps 中去做。
  2. 而在新版本中,官方將更新 state 與觸發(fā)回調(diào)重新分配到了 getDerivedStateFromProps 與 componentDidUpdate 中,使得組件整體的更新邏輯更為清晰。而且在 getDerivedStateFromProps 中還禁止了組件去訪問 this.props,強制讓開發(fā)者去比較 nextProps 與 prevState 中的值,以確保當開發(fā)者用到 getDerivedStateFromProps 這個生命周期函數(shù)時,就是在根據(jù)當前的 props 來更新組件的 state,而不是去做其他一些讓組件自身狀態(tài)變得更加不可預測的事情。

3.2. getSnapshotBeforeUpdate(prevProps, prevState)

代替componentWillUpdate。
常見的 componentWillUpdate 的用例是在組件更新前,讀取當前某個 DOM 元素的狀態(tài),并在 componentDidUpdate 中進行相應的處理。
這兩者的區(qū)別在于:

  1. 在 React 開啟異步渲染模式后,在 render 階段讀取到的 DOM 元素狀態(tài)并不總是和 commit 階段相同,這就導致在
    componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態(tài)是不安全的,因為這時的值很有可能已經(jīng)失效了。
  2. getSnapshotBeforeUpdate 會在最終的 render 之前被調(diào)用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態(tài)是可以保證與 componentDidUpdate 中一致的。
    此生命周期返回的任何值都將作為參數(shù)傳遞給componentDidUpdate()。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容