React的生命週期的三個階段 掛載、渲染、卸載

 

1. 掛載卸載過程
1.1.constructor()
1.2.componentWillMount()
1.3.componentDidMount()
1.4.componentWillUnmount ()

2. 更新過程
2.1. componentWillReceiveProps (nextProps)
2.2.shouldComponentUpdate(nextProps,nextState)
2.3.componentWillUpdate (nextProps,nextState)
2.4.componentDidUpdate(prevProps,prevState)
2.5.render()

3. React新增的生命週期(個人補充)
3.1. getDerivedStateFromProps(nextProps, prevState)
3.2. getSnapshotBeforeUpdate(prevProps, prevState)

學習React的生命週期

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

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

React生命週期圖

 

1. 掛載卸載過程

1.1.constructor()

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

1.2.componentWillMount()

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

1.3.componentDidMount()

組件第一次渲染完成,此時dom節點已經生成,可以在這裏調用ajax請求,返回數據setState後組件會重新渲染

1.4.componentWillUnmount ()

在此處完成組件的卸載和數據的銷燬。

  1. clear你在組建中所有的setTimeout,setInterval
  2. 移除所有組建中的監聽 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)

在接受父組件改變後的props需要重新渲染組件時用到的比較多

接受一個參數nextProps

通過對比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的第二個參數(回調)可以打印出新的state
  })
}

2.2.shouldComponentUpdate(nextProps,nextState)

主要用於性能優化(部分更新)

唯一用於控制組件重新渲染的生命週期,由於在react中,setState以後,state發生變化,組件會進入重新渲染的流程,在這裏return false可以阻止組件的更新

因爲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函數會插入jsx生成的dom結構,react會生成一份虛擬dom樹,在每一次組件更新時,在此react會通過其diff算法比較更新前後的新舊DOM樹,比較以後,找到最小的有差異的DOM節點,並重新渲染。

3. React新增的生命週期(補充)

React新增生命週期

3.1. getDerivedStateFromProps(nextProps, prevState)

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

// 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 中,我們一般會做以下兩件事,一是根據 props 來更新 state,二是觸發一些回調,如動畫或頁面跳轉等。

在老版本的 React 中,這兩件事我們都需要在 componentWillReceiveProps 中去做。

而在新版本中,官方將更新 state 與觸發回調重新分配到了 getDerivedStateFromProps 與 componentDidUpdate 中,使得組件整體的更新邏輯更爲清晰。而且在 getDerivedStateFromProps 中還禁止了組件去訪問 this.props,強制讓開發者去比較 nextProps 與 prevState 中的值,以確保當開發者用到 getDerivedStateFromProps 這個生命週期函數時,就是在根據當前的 props 來更新組件的 state,而不是去做其他一些讓組件自身狀態變得更加不可預測的事情。

3.2. getSnapshotBeforeUpdate(prevProps, prevState)

代替componentWillUpdate。
常見的 componentWillUpdate 的用例是在組件更新前,讀取當前某個 DOM 元素的狀態,並在 componentDidUpdate 中進行相應的處理。
這兩者的區別在於:

在 React 開啓異步渲染模式後,在 render 階段讀取到的 DOM 元素狀態並不總是和 commit 階段相同,這就導致在

componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態是不安全的,因爲這時的值很有可能已經失效了。

getSnapshotBeforeUpdate 會在最終的 render 之前被調用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態是可以保證與 componentDidUpdate 中一致的。

此生命週期返回的任何值都將作爲參數傳遞給componentDidUpdate()。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章