React 非同步渲染組件優化

本文轉自 FEPulse 公眾號(微信搜索 FEPulse,每日精選一條國內外最新前端資訊,為你把握前端脈搏)。

React 團隊在過去的一年中一直致力於非同步渲染的開發。在今年三月冰島的 JSConf 會議上,Dan Abramov 介紹了非同步渲染的優點以及實現方面的可能性。近日,React 團隊發表博客,針對非同步渲染的組件設計給出了建議。

首先,先介紹一下 React 團隊引入了的 2 個新的生命周期函數:

static getDerivedStateFromProps

該函數在一個組件被實例化或者接受到新的 props 的時候被觸發。它返回一個對象,該對象可用來更新 state。該函數與 componentDidMount 一起使用可以取代 componentWillReceiveProps的所有功能。

getSnapshotBeforeUpdate

該函數在任何變化(例如 DOM 更新)發生之前被觸發。返回值被傳給 componentDidUpdate。該函數與 componentDidUpdate 一起使用可以取代 componentWillUpdate 的所有功能

下面讓我們通過具體的例子來看一看非同步渲染中組件的優化設計。

獲取外部數據

前一段代碼使用 componentWillMount 獲取外部數據,這種方式在非同步渲染的過程中會出現請求被多次發起的情況,建議將獲取數據的步驟放在 componentDidMount 中。

添加事件監聽

這段代碼是一個組件掛載時訂閱外部事件分發器的例子,它可能會造成內存泄漏,從而導致非同步渲染被打斷,非同步渲染的中斷會導致 componentWillUnmount 不會被執行。

在 React 的設計中,componentWillMount 被執行並不能保證 componentWillUnmount 被執行,但是,componentDidMount 被執行是能保證 componentWillUnmount 被執行的。因此,建議大家在添加事件監聽的時候使用 componentDidMount 函數。

根據 props 更新 state

這兩段代碼都是根據新的 props 去更新 state 的例子。因為經常發生濫用 componentWillReceiveProps 從而導致錯誤發生的情況,React 團隊將會在未來廢棄 componentWillReceiveProps 函數,建議使用新的生命周期函數 getDerivedStateFromProps 。

調用外部函數

這是一個組件內部 state 變化時調用外部函數的例子。當我們使用 componetWillUpdate 進行級聯更新(如先渲染 DOM 元素,再根據 DOM 元素的大小添加提示工具)的時候,一個狀態的更新會導致回調函數多次被調用。建議使用 componentDidUpdate,因為它能確保每次狀態更新時回調函數僅被調用一次。

更新前獲取 DOM 屬性

這是一個通過獲取 DOM 的屬性維持滾動條位置的例子。在實現非同步渲染的時,渲染的過程中會出現渲染階段(componentWillUpdate 和 render)和提交階段(componentDidUpdate)的時間差,在這段時間裡,如果用戶改變了窗口大小,那麼 componentWillUpdate 中獲取的 scrollHeight 其實就已經過期了。

針對這個問題,React 團隊推薦使用新的生命周期函數 getSnapshotBeforeUpdate,該函數能夠在變化發生前(DOM 更新前)被立刻調用,傳遞新的參數給 componentDidUpdate,在變化發生後 componentDidUpdate 被重新調用。

最後,再次邀請大家關注我們的公眾號 FEPulse,第一時間獲取我們精心整理的最新的前端資訊。也歡迎在公眾號文章或者後台留言討論。


推薦閱讀:

一個前端工程師的上年總結
移動端手勢完美實現,Hammer介紹
前端日刊-2018.1.3
前端日刊-2017.11.19
前端日刊-2017.12.3

TAG:前端開發 | 前端工程師 | React |