iT邦幫忙

2025 iThome 鐵人賽

DAY 6
1

前言

有了前面幾篇的解釋,相信大家已經對 Signal 和 Fine-grained Reactivity 的概念有初步的認識,今天我們就回到開篇內容的主軸,接續理解 Signal 的運作原理,包含 Effect, Computed 所扮演的角色吧!

核心概念流程:資料 → 衍生 → 副作用

https://ithelp.ithome.com.tw/upload/images/20250806/201290201ITMntjbpi.png
UI = f(state) 的真正實踐在 fine-grained reactivity 裡,state 被拆分成許多最小不可分的 Signal。
任何由這些來源計算出的值都是 Computed,而所有「和 DOM / 網路 / console 等外界互動」則封裝進 Effect。

Signal ─ 單一來源

Signal 應該具備的成分

還記得前面的提問: 「什麼是 Signal?」的具體描述嗎?

你可以把 Signal 想成一個「盒子」或「容器」,它裡面裝著一個值。這個盒子有幾個關鍵特性:

  • 讀取值:你可以隨時讀取盒子裡面的值。
  • 修改值:如果 Signal 是可寫的,你可以修改盒子裡面的值。
  • 自動通知依賴者:最重要的是,當盒子裡面的值改變時,所有依賴這個 Signal 的部分(例如,你的 UI 元素、其他計算屬性等)都會被自動且高效地通知,然後它們會根據新的值進行更新。

依照前面描述你的 signal 應該要有下面圖表的特性:
https://ithelp.ithome.com.tw/upload/images/20250806/20129020moMcickoEs.png

實作並符合上述流程

  • 儲存可變值並管理一組 observers
  • 讀取時自動把目前的「觀察者」加入 observers
  • 寫入時 只做兩件事:更新值、把所有 observers 標為 dirty

流程大概會如下圖所示:
https://ithelp.ithome.com.tw/upload/images/20250806/20129020u1frfN4Spv.png

Computed ─ 快取的純函式衍生值

核心概念

  • 惰性 + 快取:只有在第一次呼叫或依賴為髒標記時才重新計算
  • 既是 observer,又能被別人觀察
  • 必須純函式,所有副作用應留給 Effect
    https://ithelp.ithome.com.tw/upload/images/20250806/20129020zZqaUl4vkq.png

Effect ─ 副作用執行者 & 排程邊界

核心概念

  • 訂閱對應 Signals / Computeds
  • 真正觸發時機受 Scheduler 控制
  • 僅執行副作用,不回傳值
    https://ithelp.ithome.com.tw/upload/images/20250806/20129020TzdL2M5JLF.png

Scheduler ─ 批次與優先權的守門員

核心概念

用來調度處理我們一開始的核心流程,把所有被 Signal 標記為髒污的 Computed 與 Effect 先暫存到佇列,再在下一個非同步時機一次性依順序批次執行:

  1. 先重算 Computed,確保資料最新。
  2. 再觸發 Effect。
  3. 執行對外副作用。

這裡以值變動為例

  • setter 只「標記」髒污 → 非同步交由 Scheduler 處理
  • Scheduler 先重算 Computed,再觸發 Effect
  • 典型實作用 queueMicrotaskrequestAnimationFrame 形成批次
    https://ithelp.ithome.com.tw/upload/images/20250806/20129020kh9WF8xNiJ.png
    Flow chart version
    https://ithelp.ithome.com.tw/upload/images/20250806/20129020XmFp5wDe8V.png

這個在框架中通常不會開放給一般開發者做調整,而且會依照不同框架採用的渲染手段而有差異,因為單純調度資料而不順帶調整渲染,會造成不必要的額外開銷。如果有,通常會做成 Adapter 的方式,讓開發者使用。

常見陷阱與解決辦法

情境 問題 解法
連環寫入 Effect 裡多次 set() → 重算過多 batch() 或 setter 內合併
無限循環 Effect 改寫自己依賴的 Signal Dev-mode 偵測 & 報錯
依賴環 Computed A 依賴 B,B 又依賴 A 建圖時偵測 cycle
記憶體洩漏 動態建立 Effect 卻沒 dispose 在 unmount 時自動清理(cleanup function)

結語

希望透過上面的圖表能夠讓大家淺顯易懂一點,這篇的重點大概綜整如下:

  • Signal:最小、可變、可追蹤的 state 單元
  • Computed:惰性快取純函式,建立衍生值
  • Effect:專責與外界互動的副作用邊界
  • Scheduler:把多次變動匯流成一次重算,確保高效

如果能把這三大角色與一個排程器拼在一起,就是 Fine-grained Reactivity「即寫即用、最小更新」的關鍵。

下一篇,我們來理解如何透過 Dependency Tracking(依賴追蹤)的方法,將這三個角色彼此緊密連接並保持運作順暢。


上一篇
Signal 與 Proxy、Virtual DOM 的區別
系列文
Reactivity 小技巧大變革:掌握 Signals 就這麼簡單!6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言