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 能捕捉到正確的資料







你可能感興趣的文章

Put Numbers in Ascending  Order

Put Numbers in Ascending Order

swap用法

swap用法

The prototype chain in JavaScript

The prototype chain in JavaScript






留言討論