?? 如果還不了解 HTML 、 CSS和JS,可以參考本號(hào)下的 HTML21 天入門教程、 CSS 21 天入門教程和JS21天入門教程。
組件的生命周期指組件從創(chuàng)建到卸載的全過程。
在這個(gè)過程中的不同階段,內(nèi)置了一些函數(shù)用以執(zhí)行需要的邏輯處理。
React 的生命周期經(jīng)過版本的迭代,有了一些變化。
這里介紹的生命周期基于版本 18。
生命周期階段
組件的生命周期有以下三個(gè)階段:
- 掛載階段(Mounting):組件實(shí)例被創(chuàng)建和插入 DOM 樹的過程。
- 更新階段(Updating):組件被重新渲染的過程。
- 卸載階段(Unmounting):組件從 DOM 樹中被刪除的過程。
它的簡(jiǎn)潔示意圖如下:
Render
階段:純凈且不包含副作用,可能會(huì)被 React 暫停、中止或重新啟動(dòng)。Commit
階段:可以使用 DOM,運(yùn)行副作用,安排更新。
掛載階段(Mounting)
掛載階段的觸發(fā)時(shí)間,是在組件實(shí)例被創(chuàng)建和插入 DOM 中時(shí)。
在這個(gè)過程中,主要以實(shí)現(xiàn)組件狀態(tài)的初始化為主。
構(gòu)造函數(shù) constructor
構(gòu)造函數(shù)在組件初始化的時(shí)候觸發(fā)一次。它主要用于 設(shè)置初始化狀態(tài) 和 綁定成員函數(shù)上下文引用。
如果不初始化 state
或不進(jìn)行方法綁定,則不需要為 React 組件實(shí)現(xiàn)構(gòu)造函數(shù)。
在 constructor()
函數(shù)中不要調(diào)用 setState()
方法。
如果需要使用內(nèi)部 state
,直接在構(gòu)造函數(shù)中為 this.state
賦值初始 state
。
constructor(props) { super(props); // 不要在這里調(diào)用 this.setState() this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this);}
切記,只能在構(gòu)造函數(shù)中直接為 this.state
賦值。
static getDerivedStateFromProps
getDerivedStateFromProps
會(huì)在調(diào)用 render
方法之前調(diào)用,并且在初始掛載及后續(xù)更新時(shí)都會(huì)被調(diào)用。
它應(yīng)返回一個(gè)對(duì)象來更新 state
,如果返回 null
則不更新任何內(nèi)容。
該函數(shù)是靜態(tài)函數(shù),函數(shù)體內(nèi)無(wú)法訪問指向當(dāng)前組件實(shí)例的指針 this
。
渲染函數(shù) render
唯一的一定不能省略的函數(shù),必須有返回值。
它僅用于渲染的純函數(shù),返回值完全取決于 state
和 props
的變化。
如果返回 null
或 false
表示不渲染任何 DOM 元素。
此渲染函數(shù)并不做實(shí)際的渲染動(dòng)作(渲染到 DOM 樹),它返回的只是一個(gè) JSX 的描述對(duì)象(及組件實(shí)例)。
何時(shí)進(jìn)行真正的渲染是有 React 庫(kù)決定的。
而 React 則是要把所有組件返回的結(jié)果綜合起來,才能知道如何產(chǎn)生真實(shí)的 DOM 樹。
也就是說,只有調(diào)用所有組件的渲染函數(shù)之后,才有可能完成 DOM 裝載,這時(shí)候才會(huì)依次調(diào)用 componentDidMount
函數(shù)作為裝載的收尾。
保持 render()
純粹,可以使服務(wù)器端渲染更加切實(shí)可行,也使組件更容易被理解。
?? 如果 shouldComponentUpdate() 返回 false,則不會(huì)調(diào)用 render()。
掛載成功函數(shù) componentDidMount
componentDidMount
會(huì)在組件掛載后(插入 DOM 樹中)立即調(diào)用。
依賴于 DOM 節(jié)點(diǎn)的初始化應(yīng)該放在這里。
常用來處理比如:監(jiān)聽事件、獲取到真實(shí) DOM 和請(qǐng)求后臺(tái)接口等。
componentDidMount
通常用于加載外部數(shù)據(jù)(即發(fā)送網(wǎng)絡(luò)請(qǐng)求)。
之所以在 componentDidMount
中而不是在構(gòu)造函數(shù)中進(jìn)行數(shù)據(jù)請(qǐng)求的原因在于:如果數(shù)據(jù)加載完畢后,即 props
已經(jīng)有值了,但是組件還沒有渲染出來,會(huì)報(bào)錯(cuò)。
但是這里有一些把數(shù)據(jù)拉取提前到 constructor
函數(shù)的思路:在 contructor
函數(shù)中,通過 Promise
來進(jìn)行數(shù)據(jù)的請(qǐng)求,并且綁定到當(dāng)前實(shí)例對(duì)象上,然后在 componentDidMount
中執(zhí)行 Promise
把數(shù)據(jù)更新到 props 上。
此函數(shù)中允許使用 setState
改變組件內(nèi) State
。
更新階段(Updating)
屬性(Props
)或狀態(tài)(State
)的改變會(huì)觸發(fā)一次更新階段操作,但是組件未必會(huì)重新渲染,這取決于 shouldComponentUpdate
。
shouldComponentUpdate
shouldComponentUpdate
指定組件是否更新鉤子。
每當(dāng)組件因?yàn)?nbsp;state
和 props
變化而更新時(shí),在重新渲染前 shouldComponentUpdate
函數(shù)都會(huì)觸發(fā)。
目的是讓 React 知道當(dāng)前 state
或 props
的改變是否影響組件的渲染。
由于 React 父組件的更新,必然會(huì)導(dǎo)致子組件的更新,因此可以在子組件中通過手動(dòng)對(duì)比 props
與 nextProps
,state
與 nextState
來確定是否需要重新渲染子組件。
如果需要?jiǎng)t返回 true
,不需要?jiǎng)t返回 false
。該函數(shù)默認(rèn)返回 true
。
?? 請(qǐng)勿在 shouldComponentUpdate
函數(shù)中使用 setState
方法,會(huì)導(dǎo)致循環(huán)調(diào)用。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate
用于保存狀態(tài)快照。
它會(huì)在組件即將掛載時(shí)觸發(fā),它的觸發(fā)在 render
渲染函數(shù)之后。render
函數(shù)并沒有完成掛載操作,而是進(jìn)行構(gòu)建抽象 UI(也就是 Virtual DOM)的工作。
這使得組件能在發(fā)生更改之前從 DOM 中捕獲一些信息。
此組件返回的任何值將作為 componentDidUpdate
的第三個(gè)參數(shù)。
componentDidUpdate
componentDidUpdate
是更新完成函數(shù)。
componentDidUpdate
方法在組件更新完后被調(diào)用。
因?yàn)榻M件已經(jīng)重新渲染,所以這里可以對(duì)組件中的 DOM 進(jìn)行操作。
在比較了 this.props 和 nextProps 的前提下可以發(fā)送網(wǎng)絡(luò)請(qǐng)求。
在 componentDidUpdate
中使用 setState 時(shí),必須加 if 條件判斷 prevProps
、prevState
和 this.state
之間的數(shù)據(jù)變化。
這使得盡管在 componentDidUpdate
中調(diào)用了 setState
進(jìn)行再更新,但是直至條件不成立,就不會(huì)造成程序死循環(huán)。
卸載階段(Unmounting)
卸載階段主要是從 DOM 樹中刪除組件,它只有一個(gè) componentWillUnmount
函數(shù)。
componentWillUnmount
componentWillUnmount
是預(yù)卸載函數(shù)。
它在組件卸載和銷毀之前觸發(fā)。
可以利用 componentWillUnmount
方法去執(zhí)行任何清理類的任務(wù)。
比如,注銷事件監(jiān)聽器、取消網(wǎng)絡(luò)請(qǐng)求、取消定時(shí)器、解綁 DOM 事件等。
要注意的是,如果在該方法中調(diào)用 setState
,不會(huì)觸發(fā) render
。
函數(shù)組件的生命周期
函數(shù)組件是更徹底的狀態(tài)驅(qū)動(dòng)抽象,甚至沒有類組件生命周期的概念,只有一個(gè)狀態(tài),React 則負(fù)責(zé)同步到 DOM。
那么在函數(shù)組件中是如何做的呢?
答案是使用鉤子。
?? 鉤子(hook)是計(jì)算機(jī)程序設(shè)計(jì)術(shù)語(yǔ)。指通過攔截軟件模塊間的函數(shù)調(diào)用、消息傳遞、事件傳遞來修改或擴(kuò)展操作系統(tǒng)、應(yīng)用程序或其他軟件組件的行為的各種技術(shù)。處理被攔截的函數(shù)調(diào)用、事件、消息的代碼,被稱為鉤子(hook)。
至于如何使用鉤子,明天繼續(xù)。
總結(jié)
- ?? 組件的生命周期有三個(gè)階段:掛載階段、更新階段和卸載階段。
- ?? 渲染函數(shù) render 是唯一的一定不能省略的函數(shù),且必須有返回值。
- ?? 函數(shù)組件是更徹底的狀態(tài)驅(qū)動(dòng)抽象,通過使用鉤子實(shí)現(xiàn)生命周期的函數(shù)處理。
該文章在 2024/12/4 15:30:50 編輯過