React基礎(六):組件渲染,生命週期詳解

引發組件重新渲染的條件:

1,state 狀態變化,組件會重新渲染。

2,父組件屬性變化,也就是父組件給子組件的 props 發生變化,也會引起重新渲染。

3,強制渲染也可以引起重新渲染。 

 

在上一篇博客,我們瞭解了第一種情況,這一篇繼續。

首先,我們先寫一對父子組件:點擊父組件的按鈕,改變 a 的值,並給子組件傳過去。

首先,在剛出來的時候,會有一次初始渲染。

這個是子組件 render 裏面的 console。

然後當按鈕被點擊的時候,你可以看到,子組件的數字確實會變,變的同時右邊的控制檯也一直在輸出“渲染了”。

這個就屬於上面的第二種情況,props 發生改變的時候,也會重新渲染。

 

第三種,就是強制渲染。這個沒啥要求,只要你需要,都可以讓它強制更新渲染。

force 就是強制的意思,update 是更新的意思。

forceUpdate 它是屬於,完全重新的把這個組件給渲染一遍。

說白了,就是不管你到底有沒有更新的必要,我就是要你更新。

但是我們一般都不會去用,也不推薦。

因爲 render 之所以不是時刻都在執行,目的就是爲了節約資源。而在沒什麼特別的理由前提下,我們是沒必要去瞎更新的,這樣會打亂 React 自身的渲染計劃,也會導致性能的下降,所以極少使用。

 

接下來我們就來說下組件的生命週期鉤子函數。

鉤子函數其實很類似於我們平常所說的事件,比如我給頁面加個事件 window.onload = function(){ ... },就是當頁面加載完成的時候,你要執行這個回調函數。

鉤子函數也是如此,它要的是在發生某種事情的時候,你要去調我的這個函數,這就是鉤子函數。

鉤子函數是存在在每一個組件當中的,那麼我們一起來看看它到底怎麼用。

 

首先,它分成三個大的階段:

1,創建階段 Mount。原來沒有這個組件,現在給它創建出來了。

2,更新階段 Update。比如說狀態發生變化,props 發生變化,或者做了強制渲染,都會導致更新的發生。

3,卸載,銷燬的階段 Unmount。

創建和卸載都是一瞬間的事,基本上來說,存在時間最久的還是更新。

實際開發中,生命週期鉤子函數中 componentDidMount 和 componentDidUpdate 用的最多。

那麼接下來,就讓我們一起來看下這些鉤子函數:

首先,我們先來一個簡單的組件,看下最先開始的創建。

創建階段 Mount:

1,先執行 constructor。

不管你是不是一個組件,不管要進行什麼工作,首先你是一個類,那麼就得遵循類最基本的要求,所以它會最先得到執行。因爲如果沒有它的話,這個類根本就創建不出來。所以這時還不算是個組件,只是 class 自身的初始化。

2,getDerivedStateFromProps:檢查需要更新的狀態。

簡單來說,它並不是一個生命週期鉤子函數,而是一個檢查函數,它的作用就是檢查更新。它需要檢查一下你的狀態變沒變,然後你哪些狀態變了,哪些沒變。所以一般我們是不去碰它的,知道有這麼個操作就行。

3,執行第一次的 render:初始渲染。

4,觸發鉤子函數 componentDidMount:組件創建完成,並且已經成功的掛載到 DOM 結構中。(對組件做一些初始化的操作,獲取數據)

 

然後我們在來看下更新的操作:

點擊按鈕,改變狀態 a 的值,自加一。

然後我們添加 shouldComponentUpdate 之後再來看看:

shouldComponentUpdate 有兩個參數 nextProps,nextState。就是接下來如果重新渲染了,會變成什麼樣的屬性和狀態。並且 shouldComponentUpdate 的返回值決定是否更新。

我們設置下次狀態裏面 a 的值,如果 %3 爲 0 的時候,就更新。說白了就是每三次更新一次。

可以看到,前 2 次點擊按鈕的時候,a 的值都是 0,第 3 次點擊的時候,a 的值才變成 3。

更新階段 Update:

1,getDerivedStateFromProps:檢查需要更新的狀態。

首先在更新的時候,如果它是無腦更新所有的東西,那麼 React 的性能就會非常的差,所以它的第一步也是 getDerivedStateFromProps。它的作用是檢查 state,props 有沒有更新,以及哪些更新了,哪些沒更新,它需要去檢查這些東西。

2,shouldComponentUpdate:即將開始更新組件,可以阻止更新發生。

這個組件應不應該更新,到目前爲止還是個問號,它在這裏需要去確定這個組件是否應該更新。在某些特殊的情況下,我們可以去阻止它的更新。就比如你打遊戲拿 5 殺的時候,突然一個彈框告訴你 windows 要升級了,它是用來詢問你的,可升可不升。

所以 shouldComponentUpdate 可以幫助我們去拒絕一些沒有意義的更新。一般來說,shouldComponentUpdate 在小的組件裏面用不上,但是對於一些大的組件,尤其是有數據交互東西,就非常的有用,它可以根據條件來更新,防止一些死循環。

3,render:如果應該更新,才更新。

這裏需要注意的是,render 更新的僅僅是虛擬 DOM,真實的 DOM 還沒更新。所以它需要在 getSnapshotBeforeUpdate 中抓住機會,它需要去把 DOM 元素中的狀態給做一個保留。

4,getSnapshotBeforeUpdate:從 DOM 中獲取狀態,已保證更新前後狀態一致。

getSnapshotBeforeUpdate 翻譯過來就是,在更新之前它要去獲取一個快照。它其實是在正式的更新之前,它需要去保存一些 DOM 的狀態,比如現在這個滾動條滾到哪個位置了,用戶輸入了哪些東西,其他東西都是怎麼設置的,在哪個位置等等,讓這些東西都得到一個保留。保留完了之後,等將來這個 DOM 元素更新了之後,它還要在恢復這個現場。這就是爲什麼在 React 裏面,它能夠自動的去維護滾動狀態的原因。

5,更新真正的 DOM 元素。

6,componentDidUpdate:更新完之後,會觸發鉤子函數。這時組件已經渲染完成。(儘量避免在 componentDidUpdate 中更新 state,不然容易造成死循環)

 

最後我們再來看看銷燬:點擊按鈕,顯示隱藏子組件。

銷燬階段 Unmount:

1,componentWillUnmount:組件銷燬,銷燬操作無法阻止。這個基本也用不上。

componentWillUnmount 不保證一定發生。比如用戶直接把瀏覽器關了,更極端點,用戶重啓,關機,或者乾脆主機炸了,這時候根本就來不及發生 componentWillUnmount。所以爲了數據的安全着想,不要把任何的數據操作往它裏面放。

 

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