React生命周期的正解
關(guān)注?入坑互聯(lián)網(wǎng)?,回復(fù)“加群”
加入我們一起學(xué)習(xí),天天進(jìn)步
前言
任何一個(gè)應(yīng)用程序都會(huì)有自己的完整生命周期。只有了解生命周期才有可能寫(xiě)出性能更好更健壯的應(yīng)用程序。當(dāng)然對(duì)比后端,前端對(duì)生命周期的定義理解使用場(chǎng)景還是有很大區(qū)別。
React生命周期
簡(jiǎn)單地說(shuō),React Component通過(guò)其定義的幾個(gè)函數(shù)來(lái)控制組件在生命周期的各個(gè)階段的動(dòng)作
組件的生命周期可分成三個(gè)狀態(tài):
① Mounting:已插入真實(shí) DOM
② Updating:正在被重新渲染
③ Unmounting:已移出真實(shí) DOM
通過(guò)下面的這張圖我們來(lái)大概了解整個(gè)過(guò)程,在做詳解:

生命周期的8個(gè)方法
1 componentWillMount()
執(zhí)行場(chǎng)景=>在render()方法之前
解釋
① 因?yàn)閏omponentWillMount是在render之前執(zhí)行,所以在這個(gè)方法中setState不會(huì)發(fā)生重新渲染(re-render);
② 這是服務(wù)端渲染(server render)中唯一調(diào)用的鉤子(hook);
③ 通常情況下,推薦用constructor()方法代替;
2 render()
執(zhí)行場(chǎng)景
① 在componentWillMount()方法之后
② 在componentWillReceive(nextProps, nextState)方法之后
3 componentDidMount()
執(zhí)行場(chǎng)景
在render()方法之后
解釋
① 這個(gè)方法會(huì)在render()之后立即執(zhí)行;
② 這里可以對(duì)DOM進(jìn)行操作,這個(gè)函數(shù)之后ref變成實(shí)際的DOM(@TODO 表述可能不清晰);
③ 這里可以加載服務(wù)器數(shù)據(jù),并且如果使用了redux之類的數(shù)據(jù)服務(wù),這里可以出發(fā)加載服務(wù)器數(shù)據(jù)的action;
④ 這里可以使用setState()方法觸發(fā)重新渲染(re-render);
4 componentWillReceiveProps(nextProps)
執(zhí)行場(chǎng)景
在已經(jīng)掛在的組件(mounted component)接收到新props時(shí)觸發(fā);
簡(jiǎn)單的說(shuō)是在除了第一次生命周期(componentWillMount -> render -> componentDidMount)之后的生命周期中出發(fā);
解釋
1 如果你需要在props發(fā)生變化(或者說(shuō)新傳入的props)來(lái)更新state,你可能需要比較this.props和nextProps, 然后使用this.setState()方法來(lái)改變this.state;
注意
① React可能會(huì)在porps傳入時(shí)即使沒(méi)有發(fā)生改變的時(shí)候也發(fā)生重新渲染, 所以如果你想自己處理改變,請(qǐng)確保比較props當(dāng)前值和下一次值; 這可能造成組件重新渲染;
② 如果你只是調(diào)用this.setState()而不是從外部傳入props, 那么不會(huì)觸發(fā)componentWillReceiveProps(nextProps)函數(shù);這就意味著: this.setState()方法不會(huì)觸發(fā)componentWillReceiveProps(), props的改變或者props沒(méi)有改變才會(huì)觸發(fā)這個(gè)方法;
5 shouldComponentUpdate(nextProps, nextState)
執(zhí)行場(chǎng)景
在接收到新props或state時(shí),或者說(shuō)在componentWillReceiveProps(nextProps)后觸發(fā)
解釋
在接收新的props或state時(shí)確定是否發(fā)生重新渲染,默認(rèn)情況返回true,表示會(huì)發(fā)生重新渲染
注意
①這個(gè)方法在首次渲染時(shí)或者forceUpdate()時(shí)不會(huì)觸發(fā);
②這個(gè)方法如果返回false, 那么props或state發(fā)生改變的時(shí)候會(huì)阻止子組件發(fā)生重新渲染;
③ 目前,如果shouldComponentUpdate(nextProps, nextState)返回false, 那么componentWillUpdate(nextProps, nextState), render(), componentDidUpdate()都不會(huì)被觸發(fā);
④Take care: 在未來(lái),React可能把shouldComponentUpdate()當(dāng)做一個(gè)小提示(hint)而不是一個(gè)指令(strict directive),并且它返回false仍然可能觸發(fā)組件重新渲染(re-render);
在React 15.3以后, React.PureComponent已經(jīng)支持使用,個(gè)人推薦,它代替了(或者說(shuō)合并了)pure-render-mixin,實(shí)現(xiàn)了shallowCompare()。
6 componentWillUpdate(nextProps, nextState)
執(zhí)行場(chǎng)景
在props或state發(fā)生改變或者shouldComponentUpdate(nextProps, nextState)觸發(fā)后, 在render()之前
解釋
這個(gè)方法在組件初始化時(shí)不會(huì)被調(diào)用;
注意
① 千萬(wàn)不要在這個(gè)函數(shù)中調(diào)用this.setState()方法.;
②如果確實(shí)需要響應(yīng)props的改變,那么你可以在componentWillReceiveProps(nextProps)中做響應(yīng)操作;
③如果shouldComponentUpdate(nextProps, nextState)返回false,那么componentWillUpdate()不會(huì)被觸發(fā);
7 componentDidUpdate(prevProps, prevState)
執(zhí)行場(chǎng)景
在發(fā)生更新或componentWillUpdate(nextProps, nextState)后
解釋
①該方法不會(huì)再組件初始化時(shí)觸發(fā);
② 使用這個(gè)方法可以對(duì)組件中的DOM進(jìn)行操作;
③ 只要你比較了this.props和nextProps,你想要發(fā)出網(wǎng)絡(luò)請(qǐng)求(nextwork requests)時(shí)就可以發(fā)出, 當(dāng)然你也可以不發(fā)出網(wǎng)絡(luò)請(qǐng)求;
注意
如果shouldComponentUpdate(nextProps, nextState)返回false, 那么componentDidUpdate(prevProps, prevState)不會(huì)被觸發(fā);
8 componentWillUnmount()
執(zhí)行場(chǎng)景
在組件卸載(unmounted)或銷毀(destroyed)之前
解釋
這個(gè)方法可以讓你處理一些必要的清理操作,比如無(wú)效的timers、interval,或者取消網(wǎng)絡(luò)請(qǐng)求,或者清理任何在componentDidMount()中創(chuàng)建的DOM元素(elements);
溫馨提示
不要在 componentWillMount 中添加事件監(jiān)聽(tīng)
在 componentDidMount 中添加事件監(jiān)聽(tīng) componentWillMount 可以被打斷或調(diào)用多次,因此無(wú)法保證事件監(jiān)聽(tīng)能在 unmount 的時(shí)候被成功卸載,可能會(huì)引起內(nèi)存泄露
由于 React 未來(lái)的版本中推出了異步渲染,在 dom 被掛載之前的階段都可以被打斷重來(lái),導(dǎo)致 componentWillMount、componentWillUpdate、componentWillReceiveProps 在一次更新中可能會(huì)被觸發(fā)多次,因此那些只希望觸發(fā)一次的副作用應(yīng)該放在 componentDidUpdate 中
這也就是為什么要把異步請(qǐng)求放在 componentDidMount 中,而不是放在 componentWillMount 中的原因,為了向后兼容
最常見(jiàn)的誤解就是 getDerivedStateFromProps 和 componentWillReceiveProps 只會(huì)在 props “改變”時(shí)才會(huì)調(diào)用。實(shí)際上只要父組件重新渲染時(shí),這兩個(gè)生命周期函數(shù)就會(huì)重新調(diào)用,不管 props 有沒(méi)有“變化”
?? 看完三件事
如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:
- 點(diǎn)贊,讓更多的人也能看到這篇內(nèi)容(收藏不點(diǎn)贊,都是耍流氓)。
- 關(guān)注公眾號(hào)「入坑互聯(lián)網(wǎng)」,不定期分享原創(chuàng)知識(shí)。
- 也看看其它文章
超實(shí)用面試題--真實(shí)面試經(jīng)驗(yàn)歸納!!!
- END -
結(jié)伴同行前端路
![]()
