Vue3?中?watch?與?watchEffect?區(qū)別及用法小結(jié)
大部分時候用 watch 顯式的指定依賴以避免不必要的重復(fù)觸發(fā),也避免在后續(xù)代碼修改或重構(gòu)時不小心引入新的依賴。watchEffect 適用于一些邏輯相對簡單,依賴源和邏輯強(qiáng)相關(guān)的場景。
你可以認(rèn)為他們是同一個功能的兩種不同形態(tài),底層的實現(xiàn)是一樣的。
- watch- 顯式指定依賴源,依賴源更新時執(zhí)行回調(diào)函數(shù)
- watchEffect - 自動收集依賴源,依賴源更新時重新執(zhí)行自身
響應(yīng)式依賴收集
首先先需要了解一下 vue 3 的響應(yīng)式是怎么工作的。我想很多文章都詳細(xì)的講過這個部分了,這里就簡單帶過一下。這里有個簡化版的 ref 的實現(xiàn):
const ref = (initialValue) => { let _value = initialValue return { get value() { track(this, 'value') // 收集依賴 return _value }, set value() { _value = value trigger(this, 'value') // 觸發(fā)依賴 } } }
訪問數(shù)據(jù)時,track 被呼叫并記錄下訪問了的字段。而當(dāng)寫入數(shù)據(jù)時,trigger 被呼叫并觸發(fā)之前所依賴了這個字段所綁定事件更新(即 effect - computed, watch, watchEffect 底層都是 effect),他們會被記錄在一個全局的 WeakMap 中,這里就不展開了,感興趣可以去看源碼。
const counter = ref(1) console.log(counter.value) // `track()` 被呼叫 counter.value = 2 // `trigger()` 被呼叫
當(dāng)我們需要函數(shù)里的依賴時,只需要記錄函數(shù)執(zhí)行的過程中 track()被呼叫的次數(shù)(和對應(yīng)的對象與字段)即可。例如:
const counter = ref(1)function foo() { console.log(counter.value) }function collectDeps() { startTracking() foo() // 在這個過程中,counter 被收集 stopTracking() }
這樣便可以知道 foo 這個函數(shù)依賴了 counter。
Watch
一個 generalised 的 watch api 應(yīng)該是這樣的(其他類似直接接受 ref 或者 reactive 作為參數(shù)的其實都是糖)。
watch( () => { /* 依賴源收集函數(shù) */ }, () => { /* 依賴源改變時的回調(diào)函數(shù) */ } )
這里的依賴源函數(shù)只會執(zhí)行一次,回調(diào)函數(shù)會在每次依賴源改變的時候觸發(fā),但是并不對回調(diào)函數(shù)進(jìn)行依賴收集。也就是說,依賴源和回調(diào)函數(shù)之間并不一定要有直接關(guān)系。
WatchEffect
watchEffect 相當(dāng)于將 watch 的依賴源和回調(diào)函數(shù)合并,當(dāng)任何你有用到的響應(yīng)式依賴更新時,該回調(diào)函數(shù)便會重新執(zhí)行。
不同于 watch,watchEffect 的回調(diào)函數(shù)會被立即執(zhí)行(即 { immediate: true })。
watchEffect( () => { /* 依賴源同時是回調(diào)函數(shù) */ } )
以下兩種用法在行為上基本等價:
watchEffect( () => console.log(counter.value) ) watch( () => counter.value, () => console.log(counter.value), { immediate: true } )
與 watch 不同的一點是,在 watchEffect 中依賴源會被重復(fù)執(zhí)行,動態(tài)新增加的依賴也會被收集,例如:
const counter = ref(0)const enabled = ref(false) watchEffect(() => { if (enabled.value) console.log(counter.value) })// (以下忽略 nextTick)// watchEffect 會被立即執(zhí)行,因為 “enabled“ 為 false, 此時僅收集到 “enabled“ 依賴counter.value += 1 // 無反應(yīng)enabled.value = true // Effect 觸發(fā),控制臺出 "1"counter.value += 1 // “counter“ 被作為新的依賴被收集,控制臺出 "2"enabled.value = false // 函數(shù)被重新執(zhí)行,無輸出counter.value += 1 // 函數(shù)被重新執(zhí)行,無輸出 (雖然 counter 已經(jīng)沒有用了,但是作為依賴還是會觸發(fā)函數(shù))
順帶一提,computed 其實類似一個帶輸出的同步版本的 watchEffect。
什么時候用什么?
推薦在大部分時候用 watch 顯式的指定依賴以避免不必要的重復(fù)觸發(fā),也避免在后續(xù)代碼修改或重構(gòu)時不小心引入新的依賴。watchEffect 適用于一些邏輯相對簡單,依賴源和邏輯強(qiáng)相關(guān)的場景(或者懶惰的場景 )。
到此這篇關(guān)于Vue3 中 watch 與 watchEffect 有什么區(qū)別?的文章就介紹到這了,更多相關(guān)Vue3 中 watch 與 watchEffect內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Vue3?中的watchEffect?特性
- vue3數(shù)據(jù)監(jiān)聽watch/watchEffect的示例代碼
- vue3中watch與watchEffect的區(qū)別
- vue3中watch和watchEffect實戰(zhàn)梳理
- Vue3中的?computed,watch,watchEffect的使用方法
- vue3中的watch和watchEffect實例詳解
- 淺談Vue3中watchEffect的具體用法
- vue3的watch和watchEffect你了解嗎
- VUE3中watch和watchEffect的用法詳解
- Vue3中watchEffect的用途淺析
- vue3中watch和watchEffect的區(qū)別
相關(guān)文章
vue2.0 獲取從http接口中獲取數(shù)據(jù),組件開發(fā),路由配置方式
今天小編就為大家分享一篇vue2.0 獲取從http接口中獲取數(shù)據(jù),組件開發(fā),路由配置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue3+element Plus如何實現(xiàn)彈框的拖拽、可點擊底層頁面功能
這篇文章主要介紹了vue3+element Plus如何實現(xiàn)彈框的拖拽、可點擊底層頁面功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11Vue?ElementUI在el-table中使用el-popover問題
這篇文章主要介紹了Vue?ElementUI在el-table中使用el-popover問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04