effectScope
?在前幾篇(Day 19~Day 21)我們見識到:
Vapor Mode 透過 跳過 Virtual DOM Diff,大幅減少運算。
Alien Signals 讓多個 composable 在大量依賴下依然「零成本」追蹤。
但 真正的挑戰 來了:
當一個頁面同時啟用大量 composable,如果沒有「範圍管理」,即使 Alien Signals 再快,也可能產生 記憶體殘留、無法清理的副作用。
effectScope
正是用來管理「響應式副作用範圍」的底層 API,而在 Vue 3.6 下,它和 Alien Signals 的結合,讓我們能在極高效的依賴追蹤下,仍然保持乾淨的清理機制。
effectScope
前面多多少少提到這個方法 effectScope
,那它究竟是什麼呢?
effectScope
是 Vue 3.2 引入的 API,用於「手動建立一個響應式範圍 (Scope)」,所有在這個範圍內建立的 ref
、reactive
、computed
、watch
都會被集中管理,並可一次 stop()
清理。
import { effectScope, ref, watch } from 'vue'
const scope = effectScope()
scope.run(() => {
const count = ref(0)
watch(count, () => console.log('count changed'))
})
scope.stop() // 一次清理所有 watcher & effect
effectScope
更強在 Vue 3.6 以前:
effectScope.stop()
只是單純清理依賴,當 scope 內有大量 composable 時,清理成本可能隨依賴數量成長。
有了 Alien Signals:
依賴追蹤變得極度輕量,scope 的 stop 也能更快完成 ,即便 scope 內有上千個 ref
/ computed
,清理時間也不再是瓶頸。
換句話說: effectScope + Alien Signals = 可控範圍 + 極低追蹤成本
回到我們在 Day 18: Effect Scope 與 onScopeDispose 的例子:
每個 Tab 都要定時抓取資料,如果直接使用 watchEffect
,切換 Tab 時要手動清理 watcher,非常麻煩。
const current = ref('home')
let stop: (() => void) | null = null
function enterTab(name: string) {
current.value = name
stop?.() // 清理上一個 Tab 的副作用
stop = watchEffect(() => fetch(`/api/${name}`))
}
effectScope
寫法:import { effectScope, ref } from 'vue'
import { useAutoRefresh } from './useAutoRefresh'
export function useTabData() {
const current = ref('home')
let tabScope: ReturnType<typeof effectScope> | null = null
function enterTab(name: string) {
current.value = name
tabScope?.stop() // 一次清理前一個 Tab 的所有副作用
tabScope = effectScope()
tabScope.run(() => {
useAutoRefresh(() => fetch(`/api/${name}`))
})
}
return { current, enterTab }
}
集中管理:所有 ref
/ watch
都在同一個 scope
快速清理:Alien Signals 讓 stop 成本極低
擴展彈性:同時放多個 composable 也不怕效能下降
effectScope
:極限測試在 Vapor Mode 專案中,可以同時啟用上千個 effectScope
,並在每個 scope 中放置大量 ref
/ watch
,透過瀏覽器 F12 Performance 面板觀察:
切換時的清理耗時
記憶體釋放曲線
GC(垃圾回收)觸發次數
GC 全名 Garbage Collection(垃圾回收),是 JavaScript 引擎(例如 V8、SpiderMonkey)內建的記憶體管理機制。
Alien Signals 的依賴追蹤幾乎為 O(1)
effectScope.stop()
即使在極大規模下也能瞬間完成
effectScope
?雖然效果驚人,但 effectScope
不是 萬靈丹。
以下情境建議使用:
動態子模組:例如「動態 Tab」、「彈窗」、「分頁資料流」
自訂 composable:需要多層副作用且需集中管理
大型即時資料流:例如 WebSocket 多頻道監聽
反之,如果只是簡單的單頁
watch
/computed
:不需要effectScope
,保持程式簡單即可。
透過這個實驗,我們可以感受到:
effectScope
= 響應範圍的「容器」
Alien Signals = 依賴追蹤的「加速引擎」
兩者結合,在 Vapor Mode 下幾乎可以做到無痛清理 + 0 延遲反應
如果說 Vapor Mode 是「跳過 Virtual DOM Diff 的快車道」,那麼
effectScope
+ Alien Signals 就是
保證車道乾淨、順暢的清潔工!