Vue3?Watch踩坑實(shí)戰(zhàn)之watch監(jiān)聽無效
ref 與 reactive
ref函數(shù)和reactive函數(shù)都是用來定義響應(yīng)式數(shù)據(jù)
但是reactive更適合定義引用類型、ref適合定義基本數(shù)據(jù)類型(可接收基本數(shù)據(jù)類型和對象)
reactive
1、 深層次響應(yīng)式,本質(zhì)是將傳入的數(shù)據(jù)包裝成一個Proxy對象
2、 參數(shù)必須是對象或者數(shù)組,如果要讓對象的某個元素實(shí)現(xiàn)響應(yīng)式時,需要使用toRefs,這樣每個都需要采用value方式訪問
ref
1、函數(shù)參數(shù)可以是基本數(shù)據(jù)類型,也可以接受對象類型
2、如果參數(shù)是對象類型時,其實(shí)底層的本質(zhì)還是reactive
3、ref響應(yīng)式原理是依賴于Object.defineProperty()的get()和set()的
watch
在自身組件監(jiān)聽 reactive 對象
let a = reactive({test: 123, bg: 456, hh: {hhh: 78}}) // 定時器 1 setTimeout(() => { a.test = 456 }, 2000) // 定時器 2 setTimeout(() => { a.hh.hhh = 56 }, 4000) // 定時器 3 setTimeout(() => { a = {} }, 6000) // watch(a, () => { // 定時器1, 2 可以觸發(fā)監(jiān)聽, 不需要deep也可以 // 定時器3 不能觸發(fā)監(jiān)聽, 因?yàn)閷ο蟮牡刂芬呀?jīng)發(fā)生改變了 console.log("change") }) // 函數(shù)返回方式 采用deep可以監(jiān)聽, 不加deep不能監(jiān)聽 watch( () => a, () => { console.log(" func change") }, { deep: true } )
為什么不加 deep不能監(jiān)聽呢,直接從源碼看
function watch(source, cb, options) { if (!isFunction(cb)) { warn2( `\`watch(fn, options?)\` signature has been moved to a separate API. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.` ); } return doWatch(source, cb, options); } function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) { // 代碼不完整,截取部分 ... if (isRef(source)) { getter = () => source.value; forceTrigger = isShallow(source); } else if (isReactive(source)) { // 這里 ,如果 source 是 reactive // 則 deep = true // 而 deep 為true 后面會 執(zhí)行traverse getter = () => source; deep = true; } else if (isArray(source)) { isMultiSource = true; forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); getter = () => source.map((s) => { if (isRef(s)) { return s.value; } else if (isReactive(s)) { return traverse(s); } else if (isFunction(s)) { return callWithErrorHandling(s, instance, 2 /* WATCH_GETTER */); } else { warnInvalidSource(s); } }); } else if (isFunction(source)) { // 如果是函數(shù), //最終 getter () => fn() // deep為false,因此不走 traverse() if (cb) { getter = () => callWithErrorHandling(source, instance, 2 /* WATCH_GETTER */); } else { getter = () => { if (instance && instance.isUnmounted) { return; } if (cleanup) { cleanup(); } return callWithAsyncErrorHandling( source, instance, 3 /* WATCH_CALLBACK */, [onCleanup] ); }; } } else { getter = NOOP; warnInvalidSource(source); } .... if (cb && deep) { const baseGetter = getter; getter = () => traverse(baseGetter()); } }
traverse 深度遍歷整個對象,深層次的訪問其所有的響應(yīng)式變量,并收集依賴
在自身組件監(jiān)聽 ref 對象
let a = ref({test: 123, bg: 456, hh: {hhh: 78}}) setTimeout(() => { a.value.test = 456 }, 2000) setTimeout(() => { a.value.hh.hhh = 56 }, 4000) setTimeout(() => { a.value = {} }, 6000) // 注意下面兩種寫法 一個是 a , 一個是 a.value // 從源碼可知, 如果是 a, 那么走isRef(source)分支, 如果是 a.value 那么走 isReactive(分支) // 這里不給出結(jié)果,動手試試 watch(a.value, (val) => { console.log(val, "change") }) watch(a, (val) => { console.log(val, "change") }) // 如果是 函數(shù)返回的方式呢? 其實(shí)也分兩種,類推即可,同時也需要注意是否需要加 deep 屬性 watch(() => a.value, (val) => { console.log(val, "change") }) watch(() => a, (val) => { console.log(val, "change") })
如果在子組件需要監(jiān)聽父組件的數(shù)據(jù),同時父組件可以通過v-model雙向綁定時需要非常注意,不然可能出現(xiàn)一些bug
如果watch監(jiān)聽無效,根據(jù)你的數(shù)據(jù)結(jié)構(gòu)分析是否是因?yàn)閷懛ú徽_導(dǎo)致。
總結(jié)
到此這篇關(guān)于Vue3 Watch踩坑實(shí)戰(zhàn)之watch監(jiān)聽無效的文章就介紹到這了,更多相關(guān)Vue3 watch監(jiān)聽無效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中的數(shù)據(jù)格式化filters、formatter方式
這篇文章主要介紹了vue中的數(shù)據(jù)格式化filters、formatter方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07Vue-cli3 $ is not defined錯誤問題及解決
這篇文章主要介紹了Vue-cli3 $ is not defined錯誤問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07在Vue3中為路由Query參數(shù)標(biāo)注類型的方法
這篇文章主要介紹了在Vue3中如何為路由Query參數(shù)標(biāo)注類型,我們就針對這個話題如何為路由Query參數(shù)標(biāo)注類型為例,看看Composable和IOC容器的代碼風(fēng)格究竟有什么不同,需要的朋友可以參考下2024-08-08Vue項(xiàng)目el-upload?上傳文件及回顯照片和下載文件功能實(shí)現(xiàn)
本次需求是上傳多種固定格式的文件,且回顯的時候,圖片可以正常顯示,文件可以進(jìn)行下載,主要采用element的el-upload組件實(shí)現(xiàn),對Vue項(xiàng)目el-upload?上傳文件及回顯照片和下載文件功能實(shí)現(xiàn)感興趣的朋友跟隨小編一起看看吧2023-12-12