2020-04-16 組件的生命周期(轉(zhuǎn)載)

React的生命周期

1. 掛載卸載過程

1.1.constructor()

1.2.componentWillMount()

1.3.componentDidMount()

1.4.componentWillUnmount ()

2. 更新過程

2.1. componentWillReceiveProps (nextProps)

2.2.shouldComponentUpdate(nextProps,nextState)

2.3.componentWillUpdate (nextProps,nextState)

2.4.componentDidUpdate(prevProps,prevState)

2.5.render()

3. React新增的生命周期(個人補充)

3.1. getDerivedStateFromProps(nextProps, prevState)

3.2. getSnapshotBeforeUpdate(prevProps, prevState)

這周開始學(xué)習(xí)React的生命周期。

React的生命周期從廣義上分為三個階段:掛載、渲染、卸載

因此可以把React的生命周期分為兩類:掛載卸載過程和更新過程。

React的生命周期圖:

React生命周期圖

1. 掛載卸載過程

1.1.constructor()

constructor()中完成了React數(shù)據(jù)的初始化,它接受兩個參數(shù):props和context,當(dāng)想在函數(shù)內(nèi)部使用這兩個參數(shù)時,需使用super()傳入這兩個參數(shù)。

注意:只要使用了constructor()就必須寫super(),否則會導(dǎo)致this指向錯誤。

1.2.componentWillMount()

componentWillMount()一般用的比較少,它更多的是在服務(wù)端渲染時使用。它代表的過程是組件已經(jīng)經(jīng)歷了constructor()初始化數(shù)據(jù)后,但是還未渲染DOM時。

1.3.componentDidMount()

組件第一次渲染完成,此時dom節(jié)點已經(jīng)生成,可以在這里調(diào)用ajax請求,返回數(shù)據(jù)setState后組件會重新渲染

1.4.componentWillUnmount ()

在此處完成組件的卸載和數(shù)據(jù)的銷毀。

clear你在組建中所有的setTimeout,setInterval

移除所有組建中的監(jiān)聽 removeEventListener

有時候我們會碰到這個warning:

Canonly update a mounted or mounting component.Thisusually? ? ? means you calledsetState()on an unmounted component.Thisisa? no-op.Pleasecheck the codeforthe undefined component.

原因:因為你在組件中的ajax請求返回setState,而你組件銷毀的時候,請求還未完成,因此會報warning

解決方法:

componentDidMount(){this.isMount===trueaxios.post().then((res)=>{this.isMount&&this.setState({// 增加條件ismount為true時aaa:res})})}componentWillUnmount(){this.isMount===false}

2. 更新過程

2.1. componentWillReceiveProps (nextProps)

在接受父組件改變后的props需要重新渲染組件時用到的比較多

接受一個參數(shù)nextProps

通過對比nextProps和this.props,將nextProps的state為當(dāng)前組件的state,從而重新渲染組件

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

2.2.shouldComponentUpdate(nextProps,nextState)

主要用于性能優(yōu)化(部分更新)

唯一用于控制組件重新渲染的生命周期,由于在react中,setState以后,state發(fā)生變化,組件會進入重新渲染的流程,在這里return false可以阻止組件的更新

因為react父組件的重新渲染會導(dǎo)致其所有子組件的重新渲染,這個時候其實我們是不需要所有子組件都跟著重新渲染的,因此需要在子組件的該生命周期中做判斷

2.3.componentWillUpdate (nextProps,nextState)

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

2.4.componentDidUpdate(prevProps,prevState)

組件更新完畢后,react只會在第一次初始化成功會進入componentDidmount,之后每次重新渲染后都會進入這個生命周期,這里可以拿到prevProps和prevState,即更新前的props和state。

2.5.render()

render函數(shù)會插入jsx生成的dom結(jié)構(gòu),react會生成一份虛擬dom樹,在每一次組件更新時,在此react會通過其diff算法比較更新前后的新舊DOM樹,比較以后,找到最小的有差異的DOM節(jié)點,并重新渲染。

3. React新增的生命周期(個人補充)

React新增生命周期

3.1. getDerivedStateFromProps(nextProps, prevState)

代替componentWillReceiveProps()。

老版本中的componentWillReceiveProps()方法判斷前后兩個 props 是否相同,如果不同再將新的 props 更新到相應(yīng)的 state 上去。這樣做一來會破壞 state 數(shù)據(jù)的單一數(shù)據(jù)源,導(dǎo)致組件狀態(tài)變得不可預(yù)測,另一方面也會增加組件的重繪次數(shù)。

舉個例子:

// beforecomponentWillReceiveProps(nextProps){if(nextProps.isLogin!==this.props.isLogin){this.setState({isLogin:nextProps.isLogin,});}if(nextProps.isLogin){this.handleClose();}}// afterstaticgetDerivedStateFromProps(nextProps,prevState){if(nextProps.isLogin!==prevState.isLogin){return{isLogin:nextProps.isLogin,};}returnnull;}componentDidUpdate(prevProps,prevState){if(!prevState.isLogin&&this.props.isLogin){this.handleClose();}}

這兩者最大的不同就是:

在 componentWillReceiveProps 中,我們一般會做以下兩件事,一是根據(jù) props 來更新 state,二是觸發(fā)一些回調(diào),如動畫或頁面跳轉(zhuǎn)等。

在老版本的 React 中,這兩件事我們都需要在 componentWillReceiveProps 中去做。

而在新版本中,官方將更新 state 與觸發(fā)回調(diào)重新分配到了 getDerivedStateFromProps 與 componentDidUpdate 中,使得組件整體的更新邏輯更為清晰。而且在 getDerivedStateFromProps 中還禁止了組件去訪問 this.props,強制讓開發(fā)者去比較 nextProps 與 prevState 中的值,以確保當(dāng)開發(fā)者用到 getDerivedStateFromProps 這個生命周期函數(shù)時,就是在根據(jù)當(dāng)前的 props 來更新組件的 state,而不是去做其他一些讓組件自身狀態(tài)變得更加不可預(yù)測的事情。

3.2. getSnapshotBeforeUpdate(prevProps, prevState)

代替componentWillUpdate。

常見的 componentWillUpdate 的用例是在組件更新前,讀取當(dāng)前某個 DOM 元素的狀態(tài),并在 componentDidUpdate 中進行相應(yīng)的處理。

這兩者的區(qū)別在于:

在 React 開啟異步渲染模式后,在 render 階段讀取到的 DOM 元素狀態(tài)并不總是和 commit 階段相同,這就導(dǎo)致在

componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態(tài)是不安全的,因為這時的值很有可能已經(jīng)失效了。

getSnapshotBeforeUpdate 會在最終的 render 之前被調(diào)用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態(tài)是可以保證與 componentDidUpdate 中一致的。

此生命周期返回的任何值都將作為參數(shù)傳遞給componentDidUpdate()。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容