React 組件生命週期詳解

Ract生命週期

React 生命週期分爲三種狀態 1. 初始化 2.更新 3.銷燬

  • 一、初始化

1、getDefaultProps()

設置默認的props,也可以用dufaultProps設置組件的默認屬性.

2、getInitialState()

在使用es6的class語法時是沒有這個鉤子函數的,可以直接在constructor中定義this.state。此時可以訪問this.props


constructor參數接受兩個參數props,context
可以獲取到父組件傳下來的的props,context,如果你想在constructor構造函數內部(注意是內部哦,在組件其他地方是可以直接接收的)使用props或context,則需要傳入,並傳入super對象。

 constructor(props,context) {
  super(props,context)
  console.log(this.props,this.context) // 在內部可以使用props和context
}

當然如果你只需要在構造函數內使用props或者context,那麼只傳入一個參數即可,如果都不可以,就都不傳。

關於ES6的class constructor和super

只要組件存在constructor,就必要要寫super,否則this指向會錯誤

 constructor() {
  console.log(this) // 報錯,this指向錯誤
}

3、componentWillMount() 組件將要掛載

組件初始化時只調用,以後組件更新不調用,整個生命週期只調用一次,此時可以修改state。

1、組件剛經歷constructor,初始完數據

2、組件還未進入render,組件還未渲染完成,dom還未渲染

componentWillMount 一般用的比較少,更多的是用在服務端渲染,(我還未使用過react服務端渲染哈,所以也寫不了很多)
但是這裏有一個問題

ajax請求能寫在willmount裏嗎?
:答案是不推薦,別這麼寫

1.雖然有些情況下並不會出錯,但是如果ajax請求過來的數據是空,那麼會影響頁面的渲染,可能看到的就是空白。
2.不利於服務端渲染,在同構的情況下,生命週期會到componentwillmount,這樣使用ajax就會出錯

4、 render()

react最重要的步驟,創建虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。

5、componentDidMount()組件渲染完成

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

  • 二、更新

6、componentWillReceiveProps(nextProps)

組件初始化時不調用,組件接受新的props時調用。

componentWillReceiveProps在接受父組件改變後的props需要重新渲染組件時用到的比較多
它接受一個參數

1.nextProps
通過對比nextProps和this.props,將nextProps setState爲當前組件的state,從而重新渲染組件

componentWillReceiveProps (nextProps) {
    nextProps.openNotice !== this.props.openNotice && this.setState({
        openNotice:nextProps.openNotice
    },() => {
      console.log(this.state.openNotice:nextProps) //將state更新爲nextProps,在setState的第二個參數(回調)可以打印出新的state
  })
}

7、shouldComponentUpdate(nextProps, nextState)

react性能優化非常重要的一環。組件接受新的state或者props時調用,我們可以設置在此對比前後兩個props和state是否相同,如果相同則返回false阻止更新,因爲相同的屬性狀態一定會生成相同的dom樹,這樣就不需要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤其是在dom結構複雜的時候。

唯一用於控制組件重新渲染的生命週期,由於在react中,setState以後,state發生變化,組件會進入重新渲染的流程,(暫時這麼理解,其實setState以後有些情況並不會重新渲染,比如數組引用不變)在這裏return false可以阻止組件的更新

因爲react父組件的重新渲染會導致其所有子組件的重新渲染,這個時候其實我們是不需要所有子組件都跟着重新渲染的,因此需要在子組件的該生命週期中做判斷

8、componentWillUpdata(nextProps, nextState)

組件初始化時不調用,只有在組件將要更新時才調用,此時可以修改state

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

9、render()

組件渲染

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

react16中 render函數允許返回一個數組,單個字符串等,不在只限製爲一個頂級DOM節點,可以減少很多不必要的div(當然注意升級你的react版本,將現有項目升到react16並不會出現什麼bug,唯一注意的是proTypes類型檢測換了名字~)

意思你現在可以這樣:

render () {
  return " "

}
或者這樣:

render () {
  return [
                <div></div>
             <div></div>

]
}


10、componentDidUpdate(prevProps,prevState)

組件初始化時不調用,組件更新完成後調用,此時可以獲取dom節點。

組件更新完畢後,react只會在第一次初始化成功會進入componentDidmount,之後每次重新渲染後都會進入這個生命週期,這裏可以拿到prevProps和prevState,即更新前的props和state。
如果你理解了組件一次重新渲染的過程,那麼你應該理解下面5處打印出來的state應該是相同的


  • 三、卸載

11、componentWillUnmount()

組件將要卸載時調用,一些事件監聽和定時器需要在此時清除。

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
}
參考:https://www.jianshu.com/p/c9bc994933d5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章