文:徐超,《react高階之路》作者
react 深入系列,深入講解了react中的重點概念、特性和模式等,旨在幫助大家加深對react的理解,以及在專案中更加靈活地使用react。元件是構建react應用的基本單位,元件需要具備資料獲取、業務邏輯處理、以及ui呈現的能力,而這些能力是要依賴於元件不同的生命週期方法的。元件的生命週期分為3個階段:掛載階段、更新階段、解除安裝階段,每個階段都包含相應的生命週期方法。因為是深入系列文章,本文不會仔細介紹每個生命週期方法的使用,而是會重點講解在使用元件生命週期時,經常遇到的疑問和錯誤使用方式。
伺服器資料請求
初學者在使用react時,常常不知道何時向伺服器傳送請求,獲取元件所需資料。對於元件所需的初始資料,最合適的地方,是在componentdidmount方法中,進行資料請求,這個時候,元件完成掛載,其代表的dom已經掛載到頁面的dom樹上,即使獲取到的資料需要直接操作dom節點,這個時候也是絕對安全的。有些人還習慣在constructor或者componentwillmount中,進行資料請求,認為這樣可以更快的獲取到資料,但它們相比componentdidmount的執行時間,提前的時間實在是太微乎其微了。另外,當進行伺服器渲染時(ssr),componentwillmount是會被呼叫兩次的,一次在伺服器端,一次在客戶端,這時候就會導致額外的請求發生。
元件進行資料請求的另一種場景:由父元件的更新導致元件的props發生變化,如果元件的資料請求依賴props,元件就需要重新進行資料請求。例如,新聞詳情元件newsdetail,在獲取新聞詳情資料時,需要傳遞新聞的id作為引數給伺服器端,當newsdetail已經處於掛載狀態時,如果點選其他新聞,newsdetail的componentdidmount並不會重新呼叫,因而componentdidmount中進行新聞詳情資料請求的方法也不會再次執行。這時候,應該在componentwillreceiveprops中,進行資料請求:
componentwillreceiveprops(nextprops)
}
如果進行資料請求的時機是由頁面上的互動行為觸發的,例如,點選查詢按鈕後,查詢資料,這時只需要在查詢按鈕的事件監聽函式中,執行資料請求即可,這種情況一般是不會有疑問的。
更新階段方法的呼叫
元件的更新是元件生命週期中最複雜的階段,也是涉及到最多生命週期方法的階段。
正常情況下,當元件發生更新時,元件的生命週期方法的呼叫順序如下:
componentwillreceiveprops -> shouldcomponentupdate -> componentwillupdate -> render -> componentdidupdate
// 元件收到新的props(props中的資料並不一定真正發生變化)-> 決定是否需要繼續執行更新過程 -> 元件代表的虛擬dom即將更新 -> 元件重新計算出新的虛擬dom -> 虛擬dom對應的真實dom更新到真實dom樹中
父元件發生更新或元件自身呼叫setstate,都會導致元件進行更新操作。父元件發生更新導致的元件更新,生命週期方法的呼叫情況同上所述。如果是元件自身呼叫setstate,導致的元件更新,其生命週期方法的呼叫情況如下:
shouldcomponentupdate -> componentwillupdate -> render -> componentdidupdate
可見,這種情況下componentwillreceiveprops並不會被呼叫。
當元件的shouldcomponentupdate返回false時,元件會停止更新過程,這時候生命週期方法的呼叫順序如下:
componentwillreceiveprops -> shouldcomponentupdate -> 結束
或(元件自身呼叫setstate,導致的元件更新):
shouldcomponentupdate -> 結束
setstate的時機
元件的生命週期方法眾多,哪些方法中可以呼叫setstate更新元件狀態?哪些方法中不可以呢?
render次數 != 瀏覽器介面更新次數
先看下面的乙個例子:
constructor(props)
} render() = this.state
return (
test
);}
componentdidmount() )
}}當我們觀察瀏覽器渲染出的頁面時,頁面中test所在div的背景色,是先顯示紅色,再變成黃色呢?還是直接就顯示為黃色呢?
答案是:直接就顯示為黃色!
這個過程中,元件的生命週期方法被呼叫的順序如下:
constructor -> componentwillmount -> render -> componentdidmount -> shouldcomponentupdate -> componentwillupdate -> render -> componentdidupdate
元件在掛載完成後,因為setstate的呼叫,將立即執行一次更新過程。雖然render方法被呼叫了兩次,但這並不會導致瀏覽器介面更新兩次,實際上,兩次dom的修改會合併成一次瀏覽器介面的更新。react官網介紹componentdidmount方法時也有以下說明:
這說明,元件render的次數不一定等於瀏覽器介面更新次數。雖然js的執行和dom的渲染分別由瀏覽器不同的執行緒完成,但js的執行會阻塞dom的渲染,而上面的兩次render是在乙個js事件週期內執行的,所以在兩次render結束前,瀏覽器不會更新介面。
下篇預告:
react 深入系列5:事件處理
新書推薦《react高階之路》
畢業於浙江大學,碩士,資深前端工程師,長期就職於能源物聯網公司遠景智慧型。8年軟體開發經驗,熟悉大前端技術,擁有豐富的web前端和移動端開發經驗,尤其對react技術棧和移動hybrid開發技術有深入的理解和實踐經驗。
美團點評廣告平台大前端團隊招收2019\2023年前端實習生(偏動效方向)
有意者郵件:[email protected]
React 元件的生命週期
在react中,元件不是真實的 dom 節點 組織頁面 文件的物件被組織在乙個樹形結構中,用來表示文件中物件的標準模型就稱為dom 而是存在於記憶體之中的一種資料結構 虛擬 dom 只有當它插入文件以後,才會變成真實的 dom 因此,reacet元件的生命週期由以下三段組成 與之對應以下五種處理函式...
react 元件的生命週期
元件的生命週期分為三個狀態 react為每個狀態都提供了兩種處理函式,will在進入狀態之前呼叫,did在函式進入狀態之後呼叫,三種狀態供給五種處理函式。此外,react還提供了兩種特殊狀態的處理函式。我們看乙個例子 es5寫法 var hello react.createclass compone...
react元件的生命週期
每個元件都包括 建立期 存在期 銷毀期 建立期 五個階段 在元件被建立的時候進入建立期 第乙個階段 getdefaultprops獲取預設屬性。作用域是建構函式 沒有引數 在這個方法 建構函式 中,元件的例項化物件還沒有被建立出來。元件的例項化物件建立出來之後,才會擁有屬性資料。es6中getdef...