react生命周期

組件的生命周期方法分以下三個(gè)階段。

Mounting
當(dāng)創(chuàng)建組件的實(shí)例并將其插入到DOM中時(shí),將調(diào)用這些方法:
constructor()
componentWillMount()
render()
componentDidMount()

Updating
更新可能是props或state的改變引起的。 當(dāng)重新渲染組件時(shí),將調(diào)用這些方法:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()

Unmounting
當(dāng)組件從dom中移除時(shí)調(diào)用:
componentWillUnmount()

找來一張圖:


react-lifecycle.png

以下詳細(xì)講解下每個(gè)方法(翻譯來的)。

render()
render()方法是必需的。調(diào)用時(shí),應(yīng)該檢查this.props和this.state并返回一個(gè)React元素。 例如<div />或您自己定義的另一個(gè)復(fù)合組件。
您也可以返回nullfalse表示您不希望任何呈現(xiàn)。 返回nullfalse時(shí),ReactDOM.findDOMNode(this)將返回null。
render()函數(shù)應(yīng)該是純函數(shù),這意味著它不會(huì)修改組件狀態(tài),每次調(diào)用它都會(huì)返回相同的結(jié)果,并且它不會(huì)直接與瀏覽器交互。 如果需要與瀏覽器交互,請(qǐng)?jiān)赾omponentDidMount()或其他生命周期方法中執(zhí)行工作。 保持render()純粹使組件更容易思考。

如果shouldComponentUpdate()返回false,則不會(huì)調(diào)用render()。

constructor(props)
組件構(gòu)造函數(shù)會(huì)在組件裝載到頁面之前調(diào)用。在實(shí)現(xiàn)React.Component子類的構(gòu)造函數(shù)時(shí),您應(yīng)該在任何其他語句之前調(diào)用super(props)
。 否則,this.props將在構(gòu)造函數(shù)中未定義,這可能會(huì)導(dǎo)致錯(cuò)誤。
構(gòu)造函數(shù)是初始化狀態(tài)的正確位置。 如果不初始化狀態(tài)并且不綁定方法,則不需要為您的React組件實(shí)現(xiàn)一個(gè)構(gòu)造函數(shù)。
可以根據(jù)props來初始化狀態(tài)。 這是一個(gè)有效的React.Component子類構(gòu)造函數(shù)的示例:

    constructor(props) {
        super(props);
        this.state = {
            color: props.initialColor
        };
    }

小心這種模式,因?yàn)闋顟B(tài)不會(huì)隨著任何props更新而更新。 你通常不想將props同步到state,而是要提升狀態(tài)。如果您通過使用props更新狀態(tài),您可能還需要實(shí)現(xiàn)componentWillReceiveProps(nextProps)來保持狀態(tài)與其最新狀態(tài)。 但是提升狀態(tài)往往比較容易,而且不容易出錯(cuò)。

componentWillMount()
在元素裝載發(fā)生之前會(huì)調(diào)用componentWillMount()。
避免在此方法中引入任何副作用或訂閱。
它在render()之前被調(diào)用,因此在該方法中同步設(shè)置狀態(tài)不會(huì)觸發(fā)重新呈現(xiàn)這是在服務(wù)器渲染上調(diào)用的唯一生命周期鉤子。 一般來說,建議使用constructor()。

componentDidMount()
在元素裝載發(fā)生之后會(huì)調(diào)用componentDidMount()。
DOM節(jié)點(diǎn)的初始化應(yīng)該在這里。 如果需要從遠(yuǎn)程端點(diǎn)加載數(shù)據(jù),這是實(shí)例化網(wǎng)絡(luò)請(qǐng)求的好地方。 此方法中的設(shè)置狀態(tài)將觸發(fā)重新渲染。

componentWillReceiveProps(nextProps)
當(dāng)組件接收到一個(gè)新的props時(shí)該方法觸發(fā). 如果需要更新狀態(tài)以響應(yīng)更改(例如,要重置它),則可以比較this.props和nextProps,并使用此方法中的this.setState()執(zhí)行狀態(tài)轉(zhuǎn)換。
請(qǐng)注意,即使props沒有改變,React也可以調(diào)用此方法,因此如果只想處理更改,請(qǐng)確保比較當(dāng)前值和下一個(gè)值。 當(dāng)父組件使您的組件重新呈現(xiàn)時(shí),可能會(huì)發(fā)生這種情況。
在裝載過程中,React不會(huì)使用初始props調(diào)用componentWillReceiveProps。 只會(huì)在某些組件的props更新時(shí)才會(huì)調(diào)用此方法。 調(diào)用this.setState通常不會(huì)觸發(fā)componentWillReceiveProps。

shouldComponentUpdate(nextProps, nextState)
使用shouldComponentUpdate()讓React知道組件的輸出是否不受當(dāng)前state或props的更改的影響。默認(rèn)行為是在每個(gè)狀態(tài)更改時(shí)重新呈現(xiàn),而在絕大多數(shù)情況下,您應(yīng)該依賴于默認(rèn)行為。
在接收到新的props或state時(shí),將在渲染之前調(diào)用shouldComponentUpdate()。默認(rèn)為true。
對(duì)于初始渲染,或者當(dāng)使用forceUpdate()時(shí),不調(diào)用此方法。
返回false不會(huì)阻止子組件在狀態(tài)更改時(shí)重新渲染。
目前,如果shouldComponentUpdate()返回false,那么將不會(huì)調(diào)用componentWillUpdate(),render()和componentDidUpdate()。請(qǐng)注意,在將來,React可以將shouldComponentUpdate()作為一個(gè)提示而不是一個(gè)strict指令,并返回false仍然可能導(dǎo)致組件的重新呈現(xiàn)。
如果在分析后確定特定組件較慢,則可以將其更改為繼承自實(shí)現(xiàn)shouldComponentUpdate()的React.PureComponent
,對(duì)props和state進(jìn)行淺比較。如果您有信心要手動(dòng)編寫,可以將this.props與nextProps和this.state與nextState進(jìn)行比較,并返回false以告知React可以跳過更新。

componentWillUpdate(nextProps, nextState)
會(huì)在render之前觸發(fā),一個(gè)新的props和state會(huì)被做為參數(shù)傳進(jìn)來 。使用此作為在更新發(fā)生之前進(jìn)行準(zhǔn)備的機(jī)會(huì)。 初始化渲染不會(huì)調(diào)用此方法。
請(qǐng)注意,您不能在此處調(diào)用this.setState()。 如果需要更新狀態(tài)以響應(yīng)更改,請(qǐng)改用componentWillReceiveProps()。
如果shouldComponentUpdate()返回false,則不會(huì)調(diào)用componentWillUpdate()。

componentDidUpdate(prevProps, prevState)
會(huì)在更新發(fā)生后立即執(zhí)行. 初始化渲染不會(huì)調(diào)用此方法。
當(dāng)組件更新時(shí),使用它作為在DOM上操作的機(jī)會(huì)。 只要您將當(dāng)前props與以前的props進(jìn)行比較。

這也是網(wǎng)絡(luò)請(qǐng)求的好地方(如果props沒有改變,則網(wǎng)絡(luò)請(qǐng)求可能不是必需的)。

componentWillUnmount()
在組件被卸載并銷毀之前,會(huì)立即調(diào)用此方法。 在此方法中執(zhí)行任何必要的清理,例如使定時(shí)器無效,取消網(wǎng)絡(luò)請(qǐng)求或清除DOM元素
(在componentDidMount中創(chuàng)建的任何DOM元素)。

setState(updater, [callback])
setState()將對(duì)組件狀態(tài)的更改插入隊(duì)列,并告訴React,該組件及其子組件需要更新狀態(tài)重新呈現(xiàn)。這是用于更新用戶界面以響應(yīng)事件處理程序和服務(wù)器響應(yīng)的主要方法。
將setState()作為請(qǐng)求而不是立即命令來更新組件。為了更好的感知性能,React可能會(huì)延遲它,然后在單次通過中更新多個(gè)組件。 React不能保證立即應(yīng)用狀態(tài)更改。
setState()并不總是立即更新組件。它可能會(huì)批量或延遲更新直。這使得在調(diào)用setState()之后立即讀取this.state是一個(gè)潛在的陷阱。最好的方法是使用componentDidUpdate或setState回調(diào)(setState(updater,callback)),其中的任何一個(gè)都會(huì)在應(yīng)用更新后都被觸發(fā)。
setState()將永遠(yuǎn)導(dǎo)致重新渲染,除非shouldComponentUpdate()返回false。

第一個(gè)參數(shù)是具有簽名的更新功能:

(prevState,props)=> stateChange

prevState是對(duì)以前狀態(tài)的引用。不應(yīng)該直接突變。相反,應(yīng)該根據(jù)prevState和props的輸入構(gòu)建一個(gè)新對(duì)象來表示更改。例如,假設(shè)我們想通過props.step來增加狀態(tài)值:

this.setState((prevState,props)=> {
  return {counter:prevState.counter + props.step};
});

updater功能接收到的prevState和props都保證是最新的。更新器的輸出與prevState進(jìn)行了淺層合并。

setState()的第二個(gè)參數(shù)是一個(gè)可選的回調(diào)函數(shù),它將在setState完成并且重新呈現(xiàn)該組件后執(zhí)行。通常我們建議使用componentDidUpdate()作為這樣的邏輯。

您可以選擇將一個(gè)對(duì)象作為第一個(gè)參數(shù)傳遞給setState()而不是一個(gè)函數(shù):

setState(stateChange,[callback])

這將執(zhí)行stateChange的淺合并到新的狀態(tài),例如調(diào)整購物車商品數(shù)量:

this.setState({quantity:2})

這種形式的setState()也是異步的,同一周期中的多個(gè)調(diào)用可以被批處理在一起。例如,如果您嘗試在同一周期內(nèi)多次增加項(xiàng)目數(shù)量,則會(huì)導(dǎo)致相當(dāng)于:

Object.assign(
  previousState,
  {quantity:state.quantity + 1},
  {quantity:state.quantity + 1},
  ...
)

后續(xù)呼叫將覆蓋同一周期中先前呼叫的值,因此數(shù)量只會(huì)增加一次。如果下一個(gè)狀態(tài)取決于以前的狀態(tài),我們建議使用updater函數(shù)形式:

this.setState((prevState)=> {
  return {counter:prevState.quantity + 1};
});

forceUpdate (callback)
默認(rèn)情況下,當(dāng)您的組件的state或props更改時(shí),您的組件將重新呈現(xiàn)。如果您的render()方法依賴于某些其他數(shù)據(jù),您可以通過調(diào)用forceUpdate()來告訴React該組件需要重新呈現(xiàn)。

調(diào)用forceUpdate()將導(dǎo)致在組件上調(diào)用render(),跳過shouldComponentUpdate()。這將觸發(fā)子組件的正常生命周期方法,包括每個(gè)子組件的shouldComponentUpdate()方法。如果標(biāo)記更改,則React仍將僅更新DOM。

通常你應(yīng)該盡量避免使用forceUpdate(),只能從render.()中的this.props和this.state讀取。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 好比我們?nèi)顺硕虝旱纳c死那一瞬之外,生命中剩下的時(shí)間都用在了每天活著的狀態(tài),對(duì)于React中的組件來講,占其總生...
    YeLqgd閱讀 10,524評(píng)論 0 7
  • 1.組件掛載和卸載時(shí) componentWillMount在render方法之前執(zhí)行,只會(huì)在組件初始化時(shí)運(yùn)行一次,...
    星月西閱讀 1,003評(píng)論 0 0
  • 譯自 React Component Lifecycle 每個(gè)組件都有若干生命周期函數(shù)。如函數(shù)名稱所示,帶有wil...
    KrisLeeSH閱讀 564評(píng)論 0 0
  • 又是一個(gè)老生常談的內(nèi)容,從ES6起已經(jīng)開始使用class的方式去創(chuàng)建組件,這種創(chuàng)建方式上的變化也帶來了寫法和方法上...
    殷灬商閱讀 465評(píng)論 0 1
  • 組件的生命周期 組件會(huì)經(jīng)過三個(gè)過程: 裝載過程(Mount),也就是把組件愛你第一次在DOM樹中渲染的過程; 更新...
    Kris_lee閱讀 498評(píng)論 0 1