深入理解Vue3 computed
在模板里寫一行 {{ sum }}
,背后卻藏著「惰性求值 + 精準依賴收集 + 臟檢查緩存」的三重魔法。本文帶你鉆進源碼,拆解 computed 如何決定「何時算、何時不、為何不能異步」。
一、使用方法
const state = reactive({ a: 1, b: 2 }) const sum = computed(() => state.a + state.b) console.log(sum.value) // 3 state.a = 10 console.log(sum.value) // 12
看似普通,但注意兩點:
- 只讀:sum 不是函數(shù),而是一個「帶緩存的 getter」。
- 懶執(zhí)行:直到第一次讀取
value
,計算函數(shù)才真正跑一遍。
二、緩存機制:dirty 標志位
源碼核心只有兩行狀態(tài)機:
let value: any let dirty = true
- dirty 為 true → 需要重新計算
- dirty 為 false → 直接返回舊值
首次讀取 sum.value
時,dirty 從 true 變?yōu)?false,并把結(jié)果存入 value
。
當依賴的響應式數(shù)據(jù)變化,調(diào)度器把 dirty 重新置為 true,但不會立即計算,而是等待下一次讀取。
這就是「緩存」的本質(zhì):用 1 bit 的布爾值換一次昂貴的計算。
三、依賴收集:effect 包裹 getter
computed 的計算函數(shù)被 effect
包裝成副作用:
const effectFn = effect(getter, { lazy: true, scheduler() { dirty = true trigger(obj, TriggerOpTypes.SET, 'value') } })
lazy: true
阻止首次執(zhí)行,實現(xiàn)惰性求值。scheduler
在依賴變化時只打標記,不立即重算,確保緩存語義。
當模板讀取 sum.value
,track
把當前渲染副作用注冊到 computed 的依賴圖;當 state.a
變化,trigger
通知渲染器重新執(zhí)行,渲染器再去讀 sum.value
,此時才真正觸發(fā)計算。
四、為什么拒絕異步?
設想一個異步 computed:
const asyncSum = computed(async () => { const res = await fetch('/api/sum?a=' + state.a) return res.json() })
問題立刻暴露:
緩存無法兌現(xiàn)
第一次讀取返回一個
Promise
,第二次讀取依賴并未變化,但緩存里存的是 Promise,無法直接返回結(jié)果。渲染時數(shù)據(jù)缺位
模板在渲染階段需要同步值,異步導致視圖出現(xiàn)空檔或閃爍。
依賴追蹤混亂
異步完成時間不確定,期間若依賴再次變化,無法確定哪一次結(jié)果是最新。
Vue 官方給出的替代方案是 watch
+ ref
:
const asyncSum = ref(0) watch(state, async () => { asyncSum.value = await fetch('/api/sum?a=' + state.a).then(r => r.json()) })
watch 不緩存、不阻塞渲染,天然適合異步副作用。
五、可寫 computed:緩存 + setter 的雙通道
const fullName = computed({ get() { return firstName.value + ' ' + lastName.value }, set(v) { [firstName.value, lastName.value] = v.split(' ') } })
- getter 走同樣的緩存邏輯。
- setter 只是普通函數(shù),無緩存要求,因此可以包含異步(但仍不推薦,因為 setter 觸發(fā)后 getter 需同步返回新值)。
總結(jié)
computed 用「dirty 位 + 惰性 effect」實現(xiàn)同步緩存,用「拒絕異步」換取數(shù)據(jù)一致性。理解了這一點,你就掌握了 Vue 性能調(diào)優(yōu)的第一把鑰匙。
到此這篇關于深入理解Vue3 computed的文章就介紹到這了,更多相關Vue3 computed內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue自定義js圖片碎片輪播圖切換效果的實現(xiàn)代碼
這篇文章主要介紹了vue自定義js圖片碎片輪播圖切換效果的實現(xiàn)代碼,需要的朋友可以參考下2019-04-04vue?內(nèi)置組件?component?的用法示例詳解
這篇文章主要介紹了vue內(nèi)置組件component的用法,本文給大家介紹了component內(nèi)置組件切換方法,通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08