Vue3中watch無法監(jiān)聽的解決辦法
下面的代碼在對ref實例賦值完之后。既:
test.value = { name: 1 }
,會發(fā)現(xiàn)不執(zhí)行watch里面的回調(diào)函數(shù)了,這是為什么呢?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../../dist/vue.global.js"></script> </head> <body> <div id="app"> </div> <script> var { createApp, ref, watch, onMounted } = Vue; var app = createApp({ setup() { var test = ref({}); onMounted(() => { test.value = { name: 1 } }) setInterval(() => { test.value.name++ }, 3000) watch(test.value, () => { debugger }) return { test, } } }) app.mount('#app') </script> <script> </script> </body> </html>
1:定義ref類型的響應式var test = ref({})
, 然后開始執(zhí)行watch(test.value, cb)
函數(shù)
2: 這時候觸發(fā)了test.value,也就是ref中的get value()
方法,該方法會執(zhí)行trackRefValue(this)
export function trackRefValue(ref: RefBase<any>) { if (shouldTrack && activeEffect) { ref = toRaw(ref) if (__DEV__) { trackEffects(ref.dep || (ref.dep = createDep()), { target: ref, type: TrackOpTypes.GET, key: 'value' }) } else { trackEffects(ref.dep || (ref.dep = createDep())) } } }
- 就是為當前ref實例,收集依賴,但是發(fā)現(xiàn)
shouldTrack
為false,activeEffect
為undefined,所以不執(zhí)行后面的邏輯
3:觸發(fā)ref的get value()
方法之后,開始執(zhí)行watch函數(shù)了
3-1: test.value是響應式屬性,所以isReactive(source)
為true, deep為true 如何包裹一層函數(shù)
if (cb && deep) { const baseGetter = getter getter = () => traverse(baseGetter()) }
4: 然后實例化構造函數(shù)const effect = new ReactiveEffect(getter, scheduler)
, 執(zhí)行effect.run()
執(zhí)行getter = () => traverse(baseGetter())
為test.value里面的屬性搜集ReactiveEffect
依賴
5: onMounted之后,直接替換test.value的值,觸發(fā)了set value()
方法
5-1:對新設置的值,重新定義proxy響應式屬性toReactive(newVal)
并且觸發(fā)triggerRefValue(this, newVal)
, 觸發(fā)依賴的執(zhí)行
set value(newVal) { const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal) newVal = useDirectValue ? newVal : toRaw(newVal) if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal this._value = useDirectValue ? newVal : toReactive(newVal) triggerRefValue(this, newVal) } }
但是get value()
的時候,沒有收集到ReactiveEffect
,所以執(zhí)行triggerRefValue(this, newVal)
的時候,沒有執(zhí)行到watch的回調(diào)函數(shù)
6:后面執(zhí)行setInterval對test.value進行賦值的時候,也沒有更新watch的回調(diào),因為set value()
的時候 重新執(zhí)行了一次toReactive(newVal)
之前收集的依賴已經(jīng)失效了
7:解決方法
// 方法一 watch(() => test.value, () => { debugger }, { deep: true }) // 方法二 watch(test, () => { debugger }, { deep: true }) // 方法三, 在test.value賦值之后執(zhí)行watch var { createApp, ref, watch, onMounted } = Vue; var app = createApp({ setup() { var test = ref({}); onMounted(() => { test.value = { name: 1 } watch(test.value, () => { debugger }) }) setInterval(() => { test.value.name++ }, 3000) // watch(test.value, () => { // debugger // }) return { test, } } }) app.mount('#app')
這個寫法,不會一開始就觸發(fā)ref實例的get value()
方法, 而是在創(chuàng)建 const effect = new ReactiveEffect(getter, scheduler)
,執(zhí)行effect.run() 的時候,觸發(fā)get value()
方法,搜集依賴
7-1:當對test.value = {name: 1}
賦值的時候,觸發(fā)set value()
方法,就可以觸發(fā)triggerRefValue(this, newVal)
執(zhí)行依賴,從而可以再次對新的值,重新搜集依賴
總結
普通的寫法進行監(jiān)聽,對ref的值進行賦值,既:test.value = { name: 1 },在get vlaue()
的時候,沒有收集 到watch的依賴,在觸發(fā)set value()
的時候,就沒有再行watch了
而加了函數(shù)包裹test.value,在執(zhí)行effect.run()
的時候,才會觸發(fā)ref的get value()
, 從而可以執(zhí)行trackRefValue(this)
收集到依賴
watch(() => test.value, () => { debugger }, { deep: true }) export function trackRefValue(ref: RefBase<any>) { if (shouldTrack && activeEffect) { ref = toRaw(ref) if (__DEV__) { trackEffects(ref.dep || (ref.dep = createDep()), { target: ref, type: TrackOpTypes.GET, key: 'value' }) } else { trackEffects(ref.dep || (ref.dep = createDep())) } } }
再觸發(fā)set value()
的時候,也就可以重新觸發(fā)effect.run()
了
到此這篇關于Vue3中watch無法監(jiān)聽的解決辦法的文章就介紹到這了,更多相關Vue3 watch無法監(jiān)聽內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue如何修改data中的obj數(shù)據(jù)的屬性
這篇文章主要介紹了vue如何修改data中的obj數(shù)據(jù)的屬性,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08詳解vue中在循環(huán)中使用@mouseenter 和 @mouseleave事件閃爍問題解決方法
這篇文章主要介紹了詳解vue中在循環(huán)中使用@mouseenter 和 @mouseleave事件閃爍問題解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04VueCli生產(chǎn)環(huán)境打包部署跨域失敗的解決
這篇文章主要介紹了VueCli生產(chǎn)環(huán)境打包部署跨域失敗的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11