016.React生命週期

舊生命週期

1.生命週期圖

react生命週期(舊).png

2.渲染流程

(1).初始化階段

由ReactDOM.render()觸發----初次渲染react

constructor() 調用構造器
constructor()中完成了React數據的初始化,它接受兩個參數:props和context,當想在函數內部使用這兩個參數時,需使用super()傳入這兩個參數。(實際開發通常省略構造器)
注意:只要使用了constructor()就必須寫super(),不然會致使this指向錯誤。ajax

componentWillMount()
組件已經經歷了constructor()初始化數據後,可是還未渲染DOM。(通常較少使用)算法

render()
DOM元素渲染(通常不把render函數放在生命週期中,這裏僅表示在這個時期會執行render)安全

componentDidMount()
組件第一次渲染完成,此時dom節點已經生成,能夠在這裏調用ajax請求,返回數據setState後組件會從新渲染,通常作一些初始化的事,如開啓定時器 發起網絡請求 訂閱消息等。性能優化

(2).更新階段

由組件內部this.setState()或父組件從新render觸發markdown

componentWillReceiveProps(nextProps)
在接受父組件改變後的props須要從新渲染組件時會用到
接受一個參數nextProps,經過對比nextProps和this.props,將nextProps的state爲當前組件的state,從而從新渲染組件網絡

shouldComponentUpdate(nextProps,nextState)dom

  • 這裏通常主要用於性能優化(部分更新)
  • 這個生命週期能夠用於控制組件從新渲染,當setState之後,state發生變化,組件會進入從新渲染的流程,在這裏return false能夠阻止組件的更新
  • 由於react父組件的從新渲染會致使其全部子組件的從新渲染,這個時候其實咱們是不須要全部子組件都跟着從新渲染的,所以須要在子組件的該生命週期中作判斷

componentWillUpdate(nextProps,nextState)
shouldComponentUpdate返回true之後,組件進入從新渲染的流程,進入componentWillUpdate,這裏一樣能夠拿到nextProps和nextState。異步

render()
render函數會插入jsx生成的dom結構,react會生成一份虛擬dom樹,在每一次組件更新時,在此react會經過其diff算法比較更新先後的新舊DOM樹,比較之後,找到最小的有差別的DOM節點,並從新渲染。函數

componentDidUpdate(prevProps,prevState)
組件更新完畢後,react只會在第一次初始化成功會進入componentDidmount,以後每次從新渲染後都會進入這個生命週期,這裏能夠拿到prevProps和prevState,即更新前的props和state。

(3).組件卸載階段

由ReactDOM.unMountComponentAtNode()觸發

componentWillUnmount()
通常作一些收尾的事 如關閉定時器 取消訂閱消息
clear你在組建中全部的setTimeout,setInterval
移除全部組建中的監聽 removeEventListener

新生命週期

1.生命週期圖

react生命週期(新).png

2.渲染流程

(1).初始化階段:

由ReactDOM.render()觸發 ---初次渲染

constructor()

getDerivedStateFromProps()
代替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,二是觸發一些回調,如動畫或頁面跳轉等。

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

使用:

static getDerivedStateFromProps(props,state){
    // 從props獲得一個派生的狀態
    // 使用場景:若state的值在任什麼時候候都取決於props 則可使用
    console.log(state) // giveCar:'toyota'
    console.log(props) // giveCar:'加長林肯'
    console.log('A--getDerivedStateFromProps')
    return (null)
    // 返回props時 狀態state會更改成props 且不會再改變
}
複製代碼

render()

componentDidMount()

(2).更新階段:

由組建內部this.setState()或父組件從新render觸發

getDerivedStateFromProps()

shouldComponentUpdata()

render()

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

  1. 在 React 開啓異步渲染模式後,在 render 階段讀取到的 DOM 元素狀態並不老是和 commit 階段相同,這就致使在componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態是不安全的,由於這時的值頗有可能已經失效了。
  2. getSnapshotBeforeUpdate 會在最終的 render 以前被調用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態是能夠保證與 componentDidUpdate 中一致的。
    今生命週期返回的任何值都將做爲參數傳遞給componentDidUpdate()。

使用:

// 在更新以前獲取快照 獲取更新以前想要的狀態
getSnapshotBeforeUpdate(){
    console.log('A--getSnapshotBeforeUpdate')
    return '快照snapshot' //傳遞給生命週期的下游 componentDidUpdate
}
複製代碼

componentDidUpdata()

(3)卸載組件:

由ReactDOM.unMountComponentAtNode()觸發
componentWillUnmount() 經常使用 通常作一些收尾的事 如關閉定時器 取消訂閱消息

相關文章
相關標籤/搜索