Vue3 中 watch 與 watchEffect 區別及用法小結
大部分時候用 watch 顯式的指定依賴以避免不必要的重復觸發,也避免在後續代碼修改或重構時不小心引入新的依賴。watchEffect 適用於一些邏輯相對簡單,依賴源和邏輯強相關的場景。
你可以認為他們是同一個功能的兩種不同形態,底層的實現是一樣的。
- watch- 顯式指定依賴源,依賴源更新時執行回調函數
- watchEffect – 自動收集依賴源,依賴源更新時重新執行自身
響應式依賴收集
首先先需要瞭解一下 vue 3 的響應式是怎麼工作的。我想很多文章都詳細的講過這個部分瞭,這裡就簡單帶過一下。這裡有個簡化版的 ref 的實現:
const ref = (initialValue) => { let _value = initialValue return { get value() { track(this, 'value') // 收集依賴 return _value }, set value() { _value = value trigger(this, 'value') // 觸發依賴 } } }
訪問數據時,track 被呼叫並記錄下訪問瞭的字段。而當寫入數據時,trigger 被呼叫並觸發之前所依賴瞭這個字段所綁定事件更新(即 effect – computed, watch, watchEffect 底層都是 effect),他們會被記錄在一個全局的 WeakMap 中,這裡就不展開瞭,感興趣可以去看源碼。
const counter = ref(1) console.log(counter.value) // `track()` 被呼叫 counter.value = 2 // `trigger()` 被呼叫
當我們需要函數裡的依賴時,隻需要記錄函數執行的過程中 track()被呼叫的次數(和對應的對象與字段)即可。例如:
const counter = ref(1)function foo() { console.log(counter.value) }function collectDeps() { startTracking() foo() // 在這個過程中,counter 被收集 stopTracking() }
這樣便可以知道 foo 這個函數依賴瞭 counter。
Watch
一個 generalised 的 watch api 應該是這樣的(其他類似直接接受 ref 或者 reactive 作為參數的其實都是糖)。
watch( () => { /* 依賴源收集函數 */ }, () => { /* 依賴源改變時的回調函數 */ } )
這裡的依賴源函數隻會執行一次,回調函數會在每次依賴源改變的時候觸發,但是並不對回調函數進行依賴收集。也就是說,依賴源和回調函數之間並不一定要有直接關系。
WatchEffect
watchEffect 相當於將 watch 的依賴源和回調函數合並,當任何你有用到的響應式依賴更新時,該回調函數便會重新執行。
不同於 watch,watchEffect 的回調函數會被立即執行(即 { immediate: true })。
watchEffect( () => { /* 依賴源同時是回調函數 */ } )
以下兩種用法在行為上基本等價:
watchEffect( () => console.log(counter.value) ) watch( () => counter.value, () => console.log(counter.value), { immediate: true } )
與 watch 不同的一點是,在 watchEffect 中依賴源會被重復執行,動態新增加的依賴也會被收集,例如:
const counter = ref(0)const enabled = ref(false) watchEffect(() => { if (enabled.value) console.log(counter.value) })// (以下忽略 nextTick)// watchEffect 會被立即執行,因為 “enabled“ 為 false, 此時僅收集到 “enabled“ 依賴counter.value += 1 // 無反應enabled.value = true // Effect 觸發,控制臺出 "1"counter.value += 1 // “counter“ 被作為新的依賴被收集,控制臺出 "2"enabled.value = false // 函數被重新執行,無輸出counter.value += 1 // 函數被重新執行,無輸出 (雖然 counter 已經沒有用瞭,但是作為依賴還是會觸發函數)
順帶一提,computed 其實類似一個帶輸出的同步版本的 watchEffect。
什麼時候用什麼?
推薦在大部分時候用 watch 顯式的指定依賴以避免不必要的重復觸發,也避免在後續代碼修改或重構時不小心引入新的依賴。watchEffect 適用於一些邏輯相對簡單,依賴源和邏輯強相關的場景(或者懶惰的場景 )。
到此這篇關於Vue3 中 watch 與 watchEffect 有什麼區別?的文章就介紹到這瞭,更多相關Vue3 中 watch 與 watchEffect內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Vue3 響應式系統實現 computed
- 深入理解Vue3裡的EffectScope
- vue3.0中的computed寫法
- 手摸手教你實現Vue3 Reactivity
- Vue3計算屬性是如何實現的