vue3下watch的使用方法示例
既然是數據監聽,監聽的是它的變化。那麼就需要能夠捕獲它的變更,於是監聽的數據必然要是響應式數據
watch(WatcherSource, Callback, [WatchOptions])
參數:
WatcherSource:想要監聽的響應式數據。
Callback:執行的回調函數,入參(newValue,oldValue)。
[WatchOptions]:deep、immediate、flush可選。
對於WatchOptions的參數配置:
deep:當需要對對象等引用類型數據進行深度監聽時,設置deep: true,默認值是false。
immediate:默認情況下watch是惰性的,設置immediate: true時,watch會在初始化時立即執行回調函數一次。
flush:控制回調函數的執行時機,。它可設置為 pre、post 或 sync。
pre:默認值,當監聽的值發生變更時,優先執行回調函數(在dom更新之前執行)。
post:dom更新渲染完畢後,執行回調函數。
sync:一旦監聽的值發生瞭變化,同步執行回調函數(建議少用)。
一,監聽單個數據ref
const count = ref(1); watch(count, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); });
可以獲取到新值和舊值。
二,監聽引用類型數據ref:深度監聽
const count = ref({ a: 1, b: 2 }); const handleClick = function () { count.value.a = 5; }; watch(count, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); });
這種情況下,我監聽的是整個數組,它是引用數據類型,內部的某一項發生瞭變更並不會被監聽到。所以watch中的代碼並沒有執行。
1,引用類型ref直接深度監聽
此時,就需要使用深度監聽:deep:true
const count = ref({ a: 1, b: 2 }); const handleClick = function () { count.value.a = 5; }; watch( count, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { deep: true } );
值發生瞭變更 Proxy {a: 5, b: 2} Proxy {a: 5, b: 2}
可以註意到的是,深度監聽的需要是這個引用數據類型自身,而不是其中的屬性。並且,他隻能獲取到新值,而獲取不到舊的值。
2,引用類型ref深拷貝深度監聽
const count = ref({ a: 1, b: 2 }); const handleClick = function () { count.value.a = 5; }; watch( () => { return { ...count.value }; }, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { deep: true } );
這樣把watch的引用類型數據源深拷貝一份,即可完成對新舊值得獲取:
值發生瞭變更 {a: 5, b: 2} {a: 1, b: 2}
三,監聽單個數據:reactive
const single = reactive({ count: 1, test: 2 }); const handleClick = function () { single.count++; }; watch( () => single.count, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { immediate: true } );
這裡主要是() => single.count,監聽的是single中的count,隻有這個屬性發生瞭變化才會觸發回調函數。這種情況下是可以獲取到新舊值的。
四,監聽引用類型數據:reactive
<template> <div class="mine-box"> <div ref="countDom">{{ single.count }}</div> <button @click="handleClick">按鈕</button> </div> </template> <script setup> import { ref, reactive, watch } from 'vue'; const single = reactive({ count: 1, test: { a: 1, b: 2 } }); const handleClick = function () { single.test.a++; }; watch( single, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { immediate: true } ); </script>
reactive的數據,用不用deep:true是沒有影響的,single中的一個屬性發生瞭變化,都能被監聽到,繼而執行回調函數。
和三中有所不同的是,這種情況下是隻能獲取到新值的。
五,immediate: true
默認情況下watch是惰性的,當我們設置immediate: true
時,watch會在初始化時立即執行回調函數。
const count = ref(1); const handleClick = function () { count.value++; }; watch( count, (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { deep: true, immediate: true } );
六,監聽多個數據源
const count = ref(1); const double = ref(2); const handleClick = function () { count.value++; double.value++; }; watch( [count, double], (newValue, oldValue) => { console.log('值發生瞭變更', newValue, oldValue); }, { deep: true, immediate: true } );
有一個值發生瞭變更,則會觸發watch,如果兩個值同時發生變更,同樣隻是觸發一次watch的回調函數。
如果想變更一格數據就觸發一次回調,可以在兩個數據變更中間加下nextTick。
七,flush的配置
1,默認情況下在dom渲染完畢前調用回調函數
默認情況下,flush的值是pre,當監聽的值發生變更時,優先執行回調函數(在dom更新之前執行)。這就意味著,如果在回調函數中有相關dom的操作,而參數裡面配置瞭immediate:true,則會報錯,因為這個時候dom還沒有被渲染,是獲取不到dom的。
接下來看下代碼:
<template> <div class="mine-box"> <div ref="countDom">{{ count }}</div> <button @click="handleClick">按鈕</button> </div> </template> <script setup> import { ref, watch } from 'vue'; const count = ref(1); const countDom = ref(null); const handleClick = function () { count.value++; }; watch( count, (newValue, oldValue) => { console.log('---', countDom.value.textContent); console.log('值發生瞭變更', newValue, oldValue); }, { deep: true } ); </script>
得到的結果:
— 1值發生瞭變更 2 1
可以看到,回調函數中新的值已經變成瞭2,而獲取到的dom還是之前的。說明默認情況下,flush的值是pre,當有值變更時,是在dom更新之前觸發回調函數的執行。
2,flush: 'post’在dom渲染完畢後執行回調函數
<template> <div class="mine-box"> <div ref="countDom">{{ count }}</div> <button @click="handleClick">按鈕</button> </div> </template> <script setup> import { ref, watch } from 'vue'; const count = ref(1); const countDom = ref(null); const handleClick = function () { count.value++; }; watch( count, (newValue, oldValue) => { console.log('---', countDom.value.textContent); console.log('值發生瞭變更', newValue, oldValue); }, { deep: true, flush: 'post' } ); </script>
得到的結果:
— 2值發生瞭變更 2 1
可以看到,是在dom更新完畢之後才調用的回調函數,這時候獲取到的dom是數據變更後更新完畢的dom。
八,總結
當使用ref創建的響應式數據時。
1,基本數據類型:可以直接監聽,可獲取新舊值。
2,引用數據類型:需要deep:true深度監聽,但是隻能獲取新值。要想獲取新舊值,要想獲取新舊值,需要監聽目標數據的深拷貝。
當使用reactive創建的響應式數據時。
1,基本數據類型:可以直接指定某個屬性進行監聽,可以獲取到新舊值。
2,引用數據類型:直接監聽創建的reactive對象,其中隻要有屬性變更,都能被監聽到。但是它隻能獲取到新值。
3,reactive創建的響應式數據,深度監聽設置是無效的,也就是deep:true/false都是能監聽到的。
deep參數
默認是false,隻有使用ref創建的響應式引用類型的數據是,才啟用。才生效。
immediate參數
默認是false,初始化的時候不執行回調函數。如果是true,初始化的時候就會執行一次回調函數。
flush參數
默認是'pre',在dom渲染之前執行回調函數,如果有immediate:true時,回調函數有獲取dom操作,則會報錯,因為初始化時dom還沒生成。
設置成'post',則是在dom渲染完畢(監聽的數據變更後dom渲染完畢)後,再執行回調函數。
總結
到此這篇關於vue3下watch的使用的文章就介紹到這瞭,更多相關vue3 watch使用內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue3怎麼數據監聽watch/watchEffect
- VUE3中watch監聽使用實例詳解
- Vue3中watch監聽對象的屬性值(監聽源必須是一個getter函數)
- vue3.0中的watch偵聽器實例詳解
- 簡單聊聊Vue中的計算屬性和屬性偵聽