生命周期是一個(gè)抽象的概念,在生命周期的整個(gè)過程,分成了很多個(gè)階段;
裝載階段(Mount),組件第一次在DOM樹中被渲染的過程;
更新過程(Update),組件狀態(tài)發(fā)生變化,重新更新渲染的過程;
卸載過程(Unmount),組件從DOM樹中被移除的過程;
React內(nèi)部為了告訴我們當(dāng)前處于哪些階段,會對我們組件內(nèi)部實(shí)現(xiàn)的某些函數(shù)進(jìn)行回調(diào),這些函數(shù)就是生命周期函數(shù):
實(shí)現(xiàn)componentDidMount函數(shù):組件已經(jīng)掛載到DOM上時(shí),就會回調(diào);
實(shí)現(xiàn)componentDidUpdate函數(shù):組件已經(jīng)發(fā)生了更新時(shí),就會回調(diào);
實(shí)現(xiàn)componentWillUnmount函數(shù):組件即將被移除時(shí),就會回調(diào);
我們可以在這些回調(diào)函數(shù)中編寫自己的邏輯代碼,來完成自己的需求功能;
我們談React生命周期時(shí),主要談的類的生命周期,因?yàn)楹瘮?shù)式組件是沒有生命周期函數(shù)的;
這里只談16.0之后的生命周期,舊生命周期不介紹


生命周期的幾個(gè)階段
在React生命周期執(zhí)行的過程中,因?yàn)镕iber(非阻塞式渲染)的加入,又可以在每個(gè)階段中分為三個(gè)片:
- Render 純凈不包含副作用,可能會被React暫停,終止,或重新啟動(dòng)
- pre-commit 可以讀取DOM
- Commit 可以使用DOM,運(yùn)行Effect,安排更新
Render 下的生命周期
constructor()
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getDerivedStateFromError()
pre-commit 下的生命周期
getSnapshotBeforeUpdate()
Commit 階段下的生命周期
componentDidMount()
componentDidUpdate()
componentDidCatch()
掛載過程
當(dāng)組件實(shí)例被創(chuàng)建并插入 DOM 中時(shí),其生命周期調(diào)用順序如下:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
更新過程
當(dāng)組件的 props 或 state 發(fā)生變化時(shí)會觸發(fā)更新。組件更新的生命周期調(diào)用順序如下:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
卸載過程
當(dāng)組件從 DOM 中移除時(shí)會調(diào)用如下方法:
componentWillUnmount()
錯(cuò)誤處理
當(dāng)渲染過程,生命周期,或子組件的構(gòu)造函數(shù)中拋出錯(cuò)誤時(shí),會調(diào)用如下方法:
static getDerivedStateFromError()
componentDidCatch()
常用周期函數(shù):
constructor()
構(gòu)造函數(shù)用于初始化props,state以及綁定this指向,如果不需要這些操作可以省略構(gòu)造函數(shù),需要注意的是:
- 構(gòu)造函數(shù)中不能調(diào)用setState, 而應(yīng)該直接給state賦值
- props是由外部傳進(jìn)來的,所以不能修改props
- 不推薦將props賦值給state
render()
render函數(shù)并不會向dom中插入元素,實(shí)際上render只是返回jsx結(jié)構(gòu),或者是數(shù)組,字符串等數(shù)據(jù),最終由ReactDOM.render渲染到dom中。
注意:在自定義的類組件中,render函數(shù)必須實(shí)現(xiàn),并且render應(yīng)該為一個(gè)根據(jù)state和props來返回結(jié)果,不造成副作用的純函數(shù)。
componentDidMount()
會在組件插入到DOM結(jié)點(diǎn)樹時(shí)進(jìn)行調(diào)用,且只會執(zhí)行一次(組件被卸載后會重新調(diào)用)
作用:
1、數(shù)據(jù)請求
2、訂閱一些行為(componentWillUnmount取消訂閱)
componentDidUpdate(prevProps, prevState, snapshot)
更新完成后會立即調(diào)用此方法,但首次渲染不會調(diào)用
snapshot的值即為getSnapshotBeforeUpdate的返回值
作用:
1、數(shù)據(jù)更新后的一些DOM操作
2、props變化后,進(jìn)行新舊props對比后的一些操作
componentWillUnmount()
會在組件卸載及銷毀之前進(jìn)行調(diào)用
不能在此調(diào)用setState
作用:
1、取消訂閱(removeListener)
2、清除未執(zhí)行完的異步任務(wù)(setTimerout\setInterval)
不常用的生命周期
static getDerivedStateFromProps(nextProps,prevState):state
props變化時(shí)被調(diào)用,以及每一次render之前都會被調(diào)用,若是父組件重新渲染,也會被調(diào)用。
用于在props發(fā)生改變時(shí)改變state相當(dāng)于被廢除的UNSAFE_componentWillReceiveProps()。
靜態(tài)方法無實(shí)例化對象,也就是this是undefeated,無法調(diào)用正常React組件方法進(jìn)行操作!
對于返回值,這個(gè)時(shí)候會進(jìn)行一個(gè)判斷 返回的新state是否發(fā)生改變
如果發(fā)生改變會停止后續(xù)生命周期流程,重新啟動(dòng)一個(gè)Update流程,又會調(diào)用getDerivedStateFromProps()
如果沒有發(fā)生改變或是null則會繼續(xù)后續(xù)流程,不會重啟一個(gè)Update流程
返回值
return newState | null(表示不更新)
shouldComponentUpdate(nextProps, nextState):boolean
在props變化或執(zhí)行setState時(shí)就會被調(diào)用,通常情況返回true。若返回false。
這個(gè)方法在掛載階段或者執(zhí)行forceUpdate時(shí)不會執(zhí)行
一般用于性能優(yōu)化
返回值
return true(需要組件更新) | false(組件忽略本次更新)
getSnapshotBeforeUpdate(prevProps, prevState):any|null
在最近的更改被提交到DOM元素前,使得組件可以在更改之前獲得當(dāng)前值。
在render之后,dom更新之前回執(zhí)行這個(gè)函數(shù),一般會在此時(shí)讀取dom更新之前的一些信息(比如滾動(dòng)條位置)。
此生命周期返回的任意值都會傳給componentDidUpdate()做為第三個(gè)參數(shù)。
通常用來做屏幕滾動(dòng)的計(jì)算,但是具體的變更要放在componentDidUpdate上做。
返回值
return any | null
static getDerivedStateFromError(error);state
當(dāng)子組件拋出錯(cuò)誤會觸發(fā)這個(gè)函數(shù),錯(cuò)誤信息為函數(shù)的參數(shù),結(jié)果可以返回一個(gè)新的值來更新state。
組件可以根據(jù)更新的state實(shí)現(xiàn)一個(gè)降級UI,此方法在“render階段”執(zhí)行,應(yīng)該為一個(gè)純函數(shù)。
返回值
return newState(需要更新的部分) | null
componentDidCatch(error, info)
錯(cuò)誤邊界會抓取組件內(nèi)JS的錯(cuò)誤,并記錄顯示回退UI。它會捕獲渲染期間,生命周期方法以及下面整個(gè)樹的構(gòu)造函數(shù)的錯(cuò)誤。
同樣當(dāng)子組件拋出錯(cuò)誤的時(shí)候回觸發(fā),第二個(gè)參數(shù)為info,其中包含了組件調(diào)用棧的信息
這個(gè)函數(shù)是在“commit階段”執(zhí)行的,所以可以在函數(shù)中調(diào)用setState來更新state。
如果一個(gè) class 組件中
定義了 static getDerivedStateFromError() 或 componentDidCatch() 這兩個(gè)生命周期方法中的任意一個(gè)(或兩個(gè))時(shí)那么它就變成一個(gè)錯(cuò)誤邊界。
當(dāng)拋出錯(cuò)誤后,請使用 static getDerivedStateFromError() 渲染備用 UI ,使用 componentDidCatch() 打印錯(cuò)誤信息。
錯(cuò)誤邊界不會生效的范圍:
- 事件處理 綁定的click事件之類的
- 異步代碼(例如 setTimeout 或 requestAnimationFrame 回調(diào)函數(shù))
服務(wù)端渲染 - 它自身拋出來的錯(cuò)誤(并非它的子組件),注意錯(cuò)誤邊界僅可以捕獲其子組件的錯(cuò)誤,它無法捕獲其自身的錯(cuò)誤。如果一個(gè)錯(cuò)誤邊界無法渲染錯(cuò)誤信息,則錯(cuò)誤會冒泡至最近的上層錯(cuò)誤邊界。
移除的生命周期
UNSAFE_componentWillMount()
UNSAFE_componentWillUpdate()
UNSAFE_componentWillReceiveProps()