首先嫌术,React生命周期分為三個(gè)階段:掛載烫扼、渲染和卸載曙求。由三種不同的形式組成:render渲染、props改變和state改變映企。由兩種過程組成:掛載卸載過程圆到、更新過程。
下面是React16.x版本之前的生命周期
舊生命周期
1.掛載卸載過程
1.1.constructor()
當(dāng)組件被實(shí)例化之后卑吭,即使不手寫構(gòu)造函數(shù)芽淡,react會(huì)自動(dòng)創(chuàng)建并執(zhí)行構(gòu)造函數(shù),并且構(gòu)造函數(shù)是最先執(zhí)行的豆赏。如果手寫了構(gòu)造函數(shù)挣菲,就必須手動(dòng)調(diào)用父類的構(gòu)造函數(shù)來實(shí)例化子類,否則會(huì)導(dǎo)致this指向錯(cuò)誤掷邦。手寫構(gòu)造函數(shù)的目的就是為了給父類也就是this添加屬性白胀,即使不添加任何屬性,react也會(huì)自動(dòng)創(chuàng)建state抚岗,只不過此時(shí)的state為null
1.2.componentWillMount()
此生命周期函數(shù)代表組件已經(jīng)經(jīng)歷了constructor()初始化數(shù)據(jù)之后或杠,但是組件未掛載,也就是還未渲染DOM 的時(shí)候宣蔚。
1.3.componentDidMount()
此生命周期函數(shù)代表組件已經(jīng)被掛載完成向抢,DOM節(jié)點(diǎn)已經(jīng)渲染完成,可以在此階段請(qǐng)求數(shù)據(jù)接口胚委,返回?cái)?shù)據(jù)之后會(huì)重新將數(shù)據(jù)渲染到組件中
1.4.componentWillUnmount ()
此過程完成組件的卸載與數(shù)據(jù)的銷毀
2.更新過程
2.1.componentWillReceiveProps (nextProps)
父組件中改變了props傳值時(shí)觸發(fā)的函數(shù), 但是此函數(shù)觸發(fā)有條件: 一挟鸠、組件初次加載時(shí)不調(diào)用此函數(shù) 二、當(dāng)組件接受了新的props時(shí)才調(diào)用此函數(shù) 三亩冬、當(dāng)父組件進(jìn)行更新以及父組件重新render(不管父組件的狀態(tài)有沒有改變)被調(diào)用后執(zhí)行
2.2.shouldComponentUpdate(nextProps,nextState)
此函數(shù)表示組件接收到新的props或者state時(shí)調(diào)用艘希,需要注意的是,初次渲染此函數(shù)不會(huì)執(zhí)行硅急。并且此函數(shù)返回bool值覆享,返回值為true時(shí),就會(huì)更新dom(使用diff算法更新),當(dāng)返回值為false時(shí)就會(huì)阻止更新
此生命周期函數(shù)可以起到性能優(yōu)化的作用营袜,因?yàn)閞eact父組件的重新渲染會(huì)導(dǎo)致其所有子組件的重新渲染撒顿,這個(gè)時(shí)候其實(shí)我們是不需要所有子組件都跟著重新渲染的,因此需要在子組件的該生命周期中做判斷
2.3.componentWillUpdate (nextProps,nextState)
此函數(shù)表示組件加載時(shí)不調(diào)用连茧,只有在組件將要更新時(shí)才調(diào)用核蘸,此時(shí)可以修改state
2.4.render()
react最重要的步驟,創(chuàng)建虛擬dom啸驯,進(jìn)行diff算法客扎,更新dom樹都在此進(jìn)行
2.5.componentDidUpdate(prevProps,prevState)
此函數(shù)表示組件數(shù)據(jù)更新已經(jīng)完成,但是組件加載時(shí)不調(diào)用,組件更新完成后調(diào)用罚斗,需要注意的是此函數(shù)在render后執(zhí)行
新生命周期
React生命周期新引入了兩個(gè)生命周期函數(shù):
getDerivedStateFromProps
徙鱼、getSnapShotBeforeUpdate
,代替在17.x版本中會(huì)廢棄的生命周期方法:componentWillMount()
针姿、componentWillReceiveProps()
袱吆、componentWillUpdate()
。16.x中新增UNSAFE前綴為別名的三個(gè)函數(shù)UNSAFE_componentWillMount()
距淫、UNSAFE_componentWillReceiveProps()
绞绒、UNSAFE_componentWillUpdate()
,并在17.x版本中會(huì)保留 UNSAFE前綴為別名的三個(gè)函數(shù)getDerivedStateFromProps()
無論是Mounting還是Updating榕暇,也無論是因?yàn)槭裁匆鸬腢pdating蓬衡,全部都會(huì)被調(diào)用getSnapshotBeforeUpdate()
被調(diào)用于render之后,可以讀取但無法使用DOM的時(shí)候彤枢。它使您的組件可以在可能更改之前從DOM捕獲一些信息(例如滾動(dòng)位置)狰晚。此生命周期返回的任何值都將作為參數(shù)傳遞給componentDidUpdate()
結(jié)合實(shí)例可以更直觀的理解react新生命周期
import React, { Component } from 'react'
export default class NewReactComponent extends Component {
constructor(props) {
super(props)
// getDefaultProps:接收初始props
// getInitialState:初始化state
// 當(dāng)組件被實(shí)例化之后,即使不手寫構(gòu)造函數(shù)缴啡,react會(huì)自動(dòng)創(chuàng)建并執(zhí)行構(gòu)造函數(shù)壁晒,并且構(gòu)造函數(shù)是最先執(zhí)行的
// 如果手寫了構(gòu)造函數(shù),就必須手動(dòng)調(diào)用父類的構(gòu)造函數(shù)來實(shí)例化子類业栅,否則會(huì)導(dǎo)致this指向錯(cuò)誤
// 手寫構(gòu)造函數(shù)的目的就是為了給父類也就是this添加屬性秒咐,即使不添加任何屬性,react也會(huì)自動(dòng)創(chuàng)建state碘裕,只不過此時(shí)的state為null
}
state = {
age:18
}
static getDerivedStateFromProps=(props, state)=> {
// 組件掛載必須要經(jīng)歷的生命周期
// 組件每次被rerender的時(shí)候反镇,包括在組件構(gòu)建之后(虛擬dom之后,實(shí)際dom掛載之前)娘汞,每次獲取新的props或state之后歹茶;
// 每次接收新的props之后都會(huì)返回一個(gè)對(duì)象作為新的state,返回null則說明不需要更新state
// 此函數(shù)是一個(gè)靜態(tài)函數(shù)你弦,所以函數(shù)體內(nèi)不能訪問this惊豺,輸出完全由輸入決定
console.log('static getDerivedStateFromProps(props, state)')
console.log(props)
console.log(state)
return state
}
componentDidCatch(error, info) {
// 獲取到j(luò)avascript錯(cuò)誤
}
changeState=()=>{
this.setState({
age:22
})
}
render() {
const {age} = this.state
const {name} = this.props
return (
<>
<h4>新生命周期</h4>
<p>props值:name:{name},age:{age}</p>
<button onClick={this.changeState}>change state</button>
</>
)
}
componentDidMount() {
// 掛載后調(diào)用且只調(diào)用一次
console.log('componentDidMount')
}
shouldComponentUpdate(nextProps, nextState) {
// nextProps和nextProps的含義就是字面量的含義,代表更新之后的狀態(tài)
// 組件Props或者state改變時(shí)觸發(fā)禽作,true:更新尸昧,false:不更新
console.log('shouldComponentUpdate')
console.log(nextProps)
console.log(nextState)
return true
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// 組件更新前觸發(fā)
// 調(diào)用順序與這個(gè)例子的順序是一樣的
console.log('getSnapshotBeforeUpdate')
return 'ok'
}
componentDidUpdate() {
// 組件更新后觸發(fā)
console.log('componentDidUpdate')
}
componentWillUnmount() {
// 組件卸載時(shí)觸發(fā)
}
}
掛載
當(dāng)組件實(shí)例被創(chuàng)建并插入 DOM 中時(shí),其生命周期調(diào)用順序如下:
更新
當(dāng)組件的 props 或 state 發(fā)生變化時(shí)會(huì)觸發(fā)更新烹俗。組件更新的生命周期調(diào)用順序如下:
卸載
當(dāng)組件從 DOM 中移除時(shí)會(huì)調(diào)用如下方法:
錯(cuò)誤處理
當(dāng)渲染過程,生命周期幢妄,或子組件的構(gòu)造函數(shù)中拋出錯(cuò)誤時(shí)兔仰,會(huì)調(diào)用如下方法:
參考資料:
https://react.docschina.org/docs/react-component.html#static-getderivedstatefromerror
https://segmentfault.com/a/1190000016617400?utm_source=tag-newest