聊聊怎么利用Memoization提高React性能

本篇文章帶大家了解一下Memoization,介紹一下為什么需要 Memoization,以及 React中實現 Memoization以提高性能的方法,希望對大家有所幫助!

聊聊怎么利用Memoization提高React性能

文章插圖

在本教程中,我們將學習如何在 React 中實現 Memoization 。 Memoization 通過緩存函數調用的結果并在再次需要時返回這些緩存的結果來提高性能 。
我們將介紹以下內容:
    React 是如何渲染視圖的?為什么需要 Memoization?如何在函數組件和類組件中實現 Memoization?注意事項
本文假設你對 React 中的類和函數組件有基本的了解 。
如果你想查閱這些主題,可以查看 React 官方文檔 components and props
https://reactjs.org/docs/components-and-props.html

聊聊怎么利用Memoization提高React性能

文章插圖

React 是如何渲染視圖的?在討論 React 中的 Memoization 細節之前,讓我們先來看看 React 是如何使用虛擬 DOM 渲染 UI 的 。 【相關推薦:Redis視頻教程】
常規 DOM 基本上包含一組用樹的形式保存的節點 。 DOM 中的每個節點代表一個 UI 元素 。 每當應用程序中出現狀態變更時,該 UI 元素及其所有子元素的相應節點都會在 DOM 樹中更新,然后會觸發 UI 重繪 。
在高效的 DOM 樹算法的幫助下,更新節點的速度更快,但重繪的速度很慢,并且當該 DOM 具有大量 UI 元素時,可能會影響性能 。 因此,在 React 中引入了虛擬 DOM 。
這是真實 DOM 的虛擬表示 。 現在,每當應用程序的狀態有任何變化時,React 不會直接更新真正的 DOM,而是創建一個新的虛擬 DOM 。 然后 React 會將此新的虛擬 DOM 與之前創建的虛擬 DOM 進行比較,找到有差異的地方(譯者注:也就是找到需要被更新節點),然后進行重繪 。
根據這些差異,虛擬 DOM 能更高效地更新真正的 DOM 。 這樣提高了性能,因為虛擬 DOM 不會簡單地更新 UI 元素及其所有子元素,而是有效地僅更新實際 DOM 中必要且最小的更改 。
為什么需要 Memoization?在上一節中,我們看到了 React 如何使用虛擬 DOM 有效地執行 DOM 更新操作來提高性能 。 在本節中,我們將介紹一個例子,該例子解釋了為了進一步提高性能而需要使用 Memoization 。
我們將創建一個父類,包含一個按鈕,用于遞增名為 count 的變量 。 父組件還調用了子組件,并向其傳遞參數 。 我們還在 render 方法中添加了 console.log() 語句:
//Parent.jsclass Parent extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick = () => { this.setState((prevState) => { return { count: prevState.count + 1 }; }); }; render() { console.log("Parent render"); return ( <div className="App"> <button onClick={this.handleClick}>Increment</button> <h2>{this.state.count}</h2> <Child name={"joe"} /> </div> ); }}export default Parent;此示例的完整代碼可在 CodeSandbox 上查看 。
我們將創建一個 Child 類,該類接受父組件傳遞的參數并將其顯示在 UI 中:
//Child.jsclass Child extends React.Component { render() { console.log("Child render"); return ( <div> <h2>{this.props.name}</h2> </div> ); }}export default Child;每當我們點擊父組件中的按鈕時,count 值都會更改 。 由于 state 變化了,因此父組件的 render 方法被執行了 。
傳遞給子組件的參數在每次父組件重新渲染時都沒有改變,因此子組件不應重新渲染 。 然而,當我們運行上面的代碼并繼續遞增 count 時,我們得到了以下輸出:
Parent renderChild renderParent renderChild renderParent renderChild render你可以在這個 sandbox 中體驗上述示例,并查看控制臺的輸出結果 。
從輸出中,我們可以看到,當父組件重新渲染時,即使傳遞給子組件的參數保持不變,子組件也會重新渲染 。 這將導致子組件的虛擬 DOM 與以前的虛擬 DOM 執行差異檢查 。 由于我們的子組件中沒有變更且重新渲染時的所有 props 都沒有變,所以真正的 DOM 不會被更新 。
真正的 DOM 不會進行不必要地更新對性能確實是有好處,但是我們可以看到,即使子組件中沒有實際更改,也會創建新的虛擬 DOM 并執行差異檢查 。 對于小型 React 組件,這種性能消耗可以忽略不計,但對于大型組件,性能影響會很大 。 為了避免這種重新渲染和虛擬 DOM 的差異檢查,我們使用 Memoization 。

推薦閱讀