React 基礎:關於性能優化


React 的渲染機制(Reconciliation)

  • 回顧 Todolist
    新增 todo 的時候,去更改資料,然後由資料去反應畫面,來保持資料與畫面永遠一致。

    假如我們現在有 100 個 todolist,當新增一個,就要把畫面重新清空,再 render,效能上就會有差別。

  • 如何快速找到要改變的地方
    state 改變,渲染了出舊 & 新的虛擬 DOM (JS 的物件),透過 diff 演算法可以進行新舊比對,比對的過程稱為:Reconciliation

  • Virtual DOM 的特點

    diff 演算法比較 Virtual DOM 修改前與修改後的樹狀結構,然後批次更新真實 DOM 中的節點。

    • 透過新舊虛擬 DOM 比對的過程,可以比較快找到兩者相異處。我們為 todoItem 加上 key 也是加快比對的速度。

    • 因為虛擬 DOM 的存在,我們可以使用同樣的原始碼(JS 物件)render 出網站、手機 APP、投影片程式。

    補充:Virtual DOM 保證的並不是在所有狀況下都比操作原本的 DOM 來得快速,而是在普遍狀況下,不需經手動優化,仍能給予不錯的效能。

如何避免 re-render

重點整理:

  1. memo() <-- 包住 component
  2. useCallback()
  3. useMemo()
  • 舉個例子:todolist Button
    父層 re-render,子層也會一起 re-render
// 另外拆成一個 component
function Button( {onClick, children }) {
    console.log("render button");
    return <button onClick={onClick}>{children}</button>
}

function App() {
    // 打字的時候,value 改變就會 re-render,同步子層 Button 也會一起,但他其實不需要 re-render
    return (
        <div className="App">
            <input
                type="text"
                placeholder="todo"
                value={value}
                onChange={handleChange}
             />
             <Button onClick={handleButtonClick}>Add todo</Button>
         </div>
        )
}
  • 如何使用 memo()
    檢查 Button() 傳入的 props 有沒有改變,如果沒有改變,就不會 re-render。

@ App.js

import { memo } from "react";

function Button( {onClick, children }) {
    console.log("render button");
    return <button onClick={onClick}>{children}</button>
}

const MemoButton = memo(Button)

function App() {
    // 打字的時候,value 改變就會 re-render,同步子層 Button 也會一起,但他其實不需要 re-render
    return (
        <div className="App">
            <input
                type="text"
                placeholder="todo"
                value={value}
                onChange={handleChange}
             />
             <Button onClick={handleButtonClick}>Add todo</Button>
         </div>
        )
}
  • useCallback:阻止 button 裡面,onClick 事件
    使用了 memo(),但 onClick 還是會影響 re-render,

@ useTodos.js

// 第一次 render 時會改變。
const handleButtonClick = useCallback(() => {
    console.log(value)
    setTodos([
        {
            id: id.current,
            content: value
        }.
        ...todos,
    ])
    setValue("");
    id.current++;
}, [setValue, setTodos, value, todos])
  • useMemo()
    只有 value 改變的時候,才會去重新渲染 s 的值。
const s = useMemo(() => {
    const.log("calculate s")
    return value ? redStyle : blueStyle;
}, [value]);

React 特別的事件機制

React 是用事件代理的機制來進行。監聽的事件是綁在 #root 上面。

  1. 效能比較好
  2. 動態新增、刪除,確保 eventlistener 能捕捉到正確的資料







你可能感興趣的文章

分辨 Slice()、Split()、Splice()

分辨 Slice()、Split()、Splice()

好用的時間套件 moment

好用的時間套件 moment

JavaScript 五四三 Ep.05 Array.prototype.find()

JavaScript 五四三 Ep.05 Array.prototype.find()






留言討論