這篇文章主要介紹了淺談React前後端同構防止重複渲染,首先解釋React前後端同構、React首屏渲染的概念。接著透過這2個概念解決服務端渲染完成後瀏覽器端重複渲染的問題。有興趣的可以了解一下
什麼叫前後端同構?
為了解決某些問題(例如SEO、提升渲染速度等)react 提供了2個方法在服務端產生一個HTML文字格式的字串。在得到了這個HTML格式的字串之後,通常會將其組裝成一個頁面直接傳回給使用者的瀏覽器。
到這裡,服務端的活已經乾完了,然後就是瀏覽器這邊工作。
瀏覽器拿到HTML文字後,立刻進行渲染將內容呈現給使用者。然後載入頁面所需的 .js 文件,然後執行 JavaScript 腳本,然後開始初始化 react 元件…………
到這裡問題就來了。 react 初始化元件後會執行元件內所有 render () 方法,然後產生虛擬DOM的樹狀結構,然後在適當的時候將虛擬dom寫入瀏覽器的真實dom。因為 react 總是會根據虛擬dom來產生真實dom,所以最後會把伺服器端渲染好的HTML全部替換掉。
上面這個事情說不是問題確實也不是問題,無非就是使用者看到頁面然後「閃現」一下。說是問題還真是個問題,產品會拿著這毛病從使用者體驗的角度在各種場合和你死磕半個月。磕累了你索性把服務端渲染關了,然後運營又拿著SEO的問題準備和你開始撕逼了。
聰明如 Facebook 的工程師當然想到了這些問題,所以他們在ReactDOMServer.renderToString(element) 方法中提供了一個 checksum 機制。
關於 checksum 官網 並沒有太多介紹,但是國內外的各路博客介紹了不少。我一直想找 react 開發者關於這個機制的介紹一直沒找到…。
前後端同構就是要確保前端和後端的dom結構一致,不會發生重複渲染。 react 使用 checksum 機制進行保障。
什麼叫React首屏渲染?
簡單的說就是 react 在瀏覽器記憶體中第一次產生的虛擬 dom 樹。切記是虛擬 dom ,而不是瀏覽器的dom。
了解 react 的應該知道,所有 react 元件都有一個 render() 方法(如果使用function方式寫的元件會把function裡的所有程式碼都塞到 render() 方法中去)。當ReactDOM.render( element, container, [callback] )方法執行時,會執行下列步驟:
所有元件的會先進行初始化(es6執行建構函式)。
所有元件的 render () 方法會被呼叫一次,完成這個過程後會得到一顆虛擬的 dom 樹。
react 會將虛擬dom轉換成瀏覽器dom,完成後呼叫元件的 componentDidMount() 方法告訴你已經裝載到瀏覽器上了。
在上面這個過程成中,步驟2完成後即為完成 react 的首屏渲染。結合 checksum 機制步驟3有可能不會執行。
當元件狀態變更時( setState() 生命週期函數被呼叫)或父元件渲染時(父元件的render() 方法被呼叫),目前元件的render() 方法都會被執行,都有可能會導致虛擬dom變更,但是這些變更和首屏渲染沒任何關係了。
React前後端同構首屏渲染
了解了同構與首屏渲染,就好理解如何解決首屏不重複渲染的問題了。
首先服務端渲染完之後會有一個checksum 值寫在根元素的屬性上:
這個checksum 是根據服務端產生的HTML內容哈希計算得到的。
然後在瀏覽器載入完所有的js檔案之後,開始執行前面介紹的 ReactDOM.render( element, container, [callback] ) 初始化渲染的三個步驟。執行完第二步驟產生虛擬dom後,react 會根虛擬dom以相同的演算法計算一個雜湊值,如果和 checksum 一致則認為伺服器已經完成渲染,不會再執行第三步。
如果checksum 比對不一致,在開發環境和測試環境會在瀏覽器console中輸出以下警告內容:
生產環境不會輸出任何警告。
同構渲染的內容就這麼多,原理其實蠻簡單的,無非就是保證DOM一致。但結合程式碼分片、非同步載入、服務端調介面非同步組裝資料等等功能後,如何確保服務端和瀏覽器端第一次渲染的dom一致還得花不少功夫。不過原理清楚了,事情總是能辦成。
上面是我整理給大家的,希望今後對大家有幫助。
相關文章:
使用JavaScript如何實現貝塞爾曲線演算法(詳細教學)
詳細介紹javascript中常用工具類別的封裝(詳細教學)
以上是使用React如何防止重複渲染的詳細內容。更多資訊請關注PHP中文網其他相關文章!