一文帶你掌握vue3中偵聽器的使用
偵聽器
偵聽器和計(jì)算屬性都可以用于偵聽響應(yīng)式數(shù)據(jù)的變化,如果需要在數(shù)據(jù)變化后執(zhí)行操作,修改依賴項(xiàng),那么就應(yīng)該使用偵聽器。
watch和watchEffect都可以偵聽數(shù)據(jù)源并執(zhí)行回調(diào)操作,不同的是他們追蹤響應(yīng)式依賴的方式。
watch:只追蹤指定的數(shù)據(jù)源,所以可以精確地控制回調(diào)函數(shù)的觸發(fā)時(shí)機(jī)
watchEffect:自動(dòng)追蹤回調(diào)內(nèi)的響應(yīng)式數(shù)據(jù),相比watch更加簡潔,但有時(shí)其響應(yīng)性依賴關(guān)系會(huì)不那么明確。
watch函數(shù)
第一個(gè)參數(shù)需要指定需要偵聽的數(shù)據(jù)。
可以是響應(yīng)式數(shù)據(jù)(ref、reactive、computed...)、getter函數(shù)、也可以是以上數(shù)據(jù)源組成的數(shù)組,也就是同時(shí)偵聽多個(gè)數(shù)據(jù)源。
第二個(gè)參數(shù)是在偵聽到數(shù)據(jù)變動(dòng)時(shí),需要執(zhí)行的回調(diào)方法。
該回調(diào)方法有兩個(gè)參數(shù),第一個(gè)為數(shù)據(jù)更新后的值,第二個(gè)為數(shù)據(jù)更新前的值。
import { ref, watch } from 'vue'
const count = ref(0)
const price = ref(10)
// 偵聽響應(yīng)式數(shù)據(jù)
watch(count, (newVal, oldVal) => {
// 每當(dāng)count更新時(shí),都會(huì)執(zhí)行這里的函數(shù)
console.log("new count:", newVal) // 1 更新后的值
console.log("old count:", oldVal) // 0 更新前的值
})
// 偵聽getter函數(shù)
watch(
() => count.value * price.value,
(newVal, oldVal) => {
// 每當(dāng)count或者price更新時(shí),都會(huì)執(zhí)行這里的函數(shù)
console.log("新總價(jià):", newVal) // 10 更新后的值
console.log("舊總價(jià):", oldVal) // 0 更新前的值
})
// 使用數(shù)組偵聽多個(gè)數(shù)據(jù)源
watch(
[count, () => price.value],
(newValArr, oldValArr) => {
// 每當(dāng)count或者price更新時(shí),都會(huì)執(zhí)行這里的函數(shù)
// 需要注意此時(shí)的回調(diào)數(shù)據(jù)為數(shù)組
// newValArr[0] count
// newValArr[1] () => price.value]
// oldValArr 同上
console.log(newValArr) // [1, 10] 更新后的值
console.log(oldValArr) // [0, 10] 更新前的值
})
count.value++ // 更新count值可選配置
以上兩個(gè)參數(shù)在偵聽器中是必傳的,除此之外watch函數(shù)還有一些可選配置。
立即執(zhí)行
watch默認(rèn)是在數(shù)據(jù)源更新時(shí)才會(huì)執(zhí)行回調(diào),如果想要在創(chuàng)建時(shí)立刻執(zhí)行回調(diào)函數(shù),就可以通過傳入 immediate:true 使偵聽器的回調(diào)立即執(zhí)行
const count = ref(0)
watch(count, (newVal,oldVal) => {
console.log(newVal) // 0
console.log(oldVal) // undefind
}, {
immediate: true // 創(chuàng)建時(shí)立即執(zhí)行一次回調(diào)
})深層偵聽器
給watch函數(shù)傳入一個(gè)響應(yīng)式對(duì)象,會(huì)隱式地創(chuàng)建一個(gè)深層偵聽器——該回調(diào)函數(shù)在所有嵌套的變更時(shí)都會(huì)被觸發(fā):
const obj1 = reactive({ val: 1 })
watch(obj1, (newVal, oldVal) => {
// 在obj的嵌套屬性變更時(shí)觸發(fā)
// 注意此處的newVal oldVal的值是相等的
// 因?yàn)樗麄兪峭粋€(gè)對(duì)象
})
const obj2 = ref({ val: 2 })
// 傳入ref偵聽的對(duì)象時(shí),添加.value才會(huì)默認(rèn)創(chuàng)建深層偵聽
watch(obj2.value, (newVal, oldVal) => {})
obj1.val++
obj2.value.val++當(dāng)直接傳入ref創(chuàng)建的對(duì)象或是返回響應(yīng)式對(duì)象的getter函數(shù)時(shí),只有在它們的對(duì)象被整個(gè)替換時(shí)才會(huì)觸發(fā)回調(diào)。如果也想創(chuàng)建深層偵聽,可以通過傳入deep:true強(qiáng)制轉(zhuǎn)成深層偵聽器。
// 當(dāng)直接傳入ref創(chuàng)建的對(duì)象或是返回響應(yīng)式對(duì)象的getter函數(shù)時(shí)
// 只有在它們的對(duì)象被整個(gè)替換時(shí)才會(huì)觸發(fā)回調(diào)
// 例:obj2.value = { val: 3 }
// 傳入deep選項(xiàng)即可創(chuàng)建深層偵聽
// getter函數(shù)
watch(() => obj2.value, (newVal, oldVal) => {
// 注意此處的newVal oldVal的值是相等的
// 除非替換掉整個(gè)obj2.value
}, {
deep: true // 當(dāng)值變更時(shí)觸發(fā)回調(diào)
})
// ref創(chuàng)建的對(duì)象數(shù)據(jù)
watch(obj2, (newVal, oldVal) => {
// 注意此處的newVal oldVal的值是相等的
// 除非替換掉整個(gè)obj2.value
}, {
deep: true // 當(dāng)值變更時(shí)觸發(fā)回調(diào)
})watchEffect函數(shù)
和計(jì)算屬性一樣,不需要指定要偵聽的響應(yīng)式數(shù)據(jù),而是會(huì)自動(dòng)跟蹤回調(diào)的響應(yīng)式依賴,并在依賴變化時(shí)重新執(zhí)行回調(diào)函數(shù);
并且創(chuàng)建后回調(diào)會(huì)立即執(zhí)行一次(不需要傳入 immediate:true);
相比watch函數(shù)更加簡潔方便。
import { ref, watchEffect } from 'vue';
const count = ref(0)
watchEffect(() => {
console.log(count.value) // 0
})停止偵聽
當(dāng)業(yè)務(wù)需要,或者在異步操作中創(chuàng)建偵聽器時(shí),
可以通過以下方法來停止偵聽器。
const unwatch = watchEffect(() => { })
// 當(dāng)不需要時(shí)調(diào)用 unwatch() 即可銷毀偵聽
unwatch()setTimeout(() => {
// 在同步中創(chuàng)建的偵聽器在組件銷毀時(shí),自動(dòng)停止,而異步中創(chuàng)建的不會(huì)!
watchEffect(() => {})
}, 100)DOM更新后觸發(fā)回調(diào)
偵聽的數(shù)據(jù)源變更,有可能同時(shí)觸發(fā)vue組件更新與偵聽器回調(diào)。
默認(rèn)情況下,回調(diào)會(huì)在組件更新之前執(zhí)行,也就是在回調(diào)中獲取dom獲取到的是vue組件更新之前的狀態(tài),
如果想要在回調(diào)中訪問更新之后的狀態(tài)那么就需要傳入flush: 'post'選項(xiàng)
watch(count, ()=>{
}, {
flush: 'post'
})
watchEffect(()=>{
}, {
flush: 'post'
})注意點(diǎn)
watch函數(shù)的回調(diào)參數(shù)
回調(diào)函數(shù)的參數(shù)有兩個(gè),第一個(gè)為"新值",第二個(gè)為"舊值",如果只需要使用"新值",可以忽略第二個(gè)值,
如果監(jiān)聽的數(shù)據(jù)是對(duì)象,那么他們的"新值"與"舊值"是相等的,因?yàn)槎贾赶蛲粋€(gè)內(nèi)存地址,除非整個(gè)替換掉。
盡量不要在異步中創(chuàng)建偵聽
盡量不要在異步中創(chuàng)建偵聽,在異步中創(chuàng)建的偵聽不會(huì)自動(dòng)銷毀,如果在異步中創(chuàng)建偵聽,請(qǐng)手動(dòng)結(jié)束偵聽。
到此這篇關(guān)于一文帶你掌握vue3中偵聽器的使用的文章就介紹到這了,更多相關(guān)vue3偵聽器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue.js計(jì)算屬性computed用法實(shí)例分析
這篇文章主要介紹了vue.js計(jì)算屬性computed用法,結(jié)合實(shí)例形式分析了vue.js使用computed方式進(jìn)行屬性計(jì)算的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07
VUE3+Element-plus中el-form的使用示例代碼
這篇文章主要介紹了VUE3+Element-plus中el-form的使用示例代碼,本文通過圖文示例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
vue3中使用props和emits并指定其類型與默認(rèn)值
props是Vue3中的一個(gè)重要概念,它允許我們將數(shù)據(jù)從父組件傳遞到子組件,下面這篇文章主要給大家介紹了關(guān)于vue3中使用props和emits并指定其類型與默認(rèn)值的相關(guān)資料,需要的朋友可以參考下2023-04-04
vue的列表交錯(cuò)過渡實(shí)現(xiàn)代碼示例
這篇文章主要介紹了vue的列表交錯(cuò)過渡實(shí)現(xiàn)代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
詳解如何在vue項(xiàng)目中引入elementUI組件
這篇文章主要介紹了詳解如何在vue項(xiàng)目中引入elementUI組件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
Vue3實(shí)現(xiàn)預(yù)覽PDF文件的多種方式(超簡單)
在Vue項(xiàng)目中實(shí)現(xiàn)PDF文件預(yù)覽是許多開發(fā)者可能會(huì)遇到的需求,尤其是在開發(fā)海外后臺(tái)管理系統(tǒng)時(shí),由于某些用戶上傳的文件格式為PDF,而Vue本身并不直接支持PDF文件的預(yù)覽功能,這就需要借助一些第三方的插件或者工具來完成,下面詳細(xì)地介紹幾種在Vue3中實(shí)現(xiàn)PDF文件預(yù)覽的方法2025-03-03
vue業(yè)務(wù)實(shí)例之組件遞歸及其應(yīng)用
目中出現(xiàn)多級(jí)菜單時(shí),需要多層for循環(huán)時(shí),但是當(dāng)菜單增加層級(jí)時(shí),需要在頁面結(jié)構(gòu)中增加一層for循環(huán),這時(shí)我們可以使用組件遞歸的思想來實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于vue業(yè)務(wù)實(shí)例之組件遞歸及其應(yīng)用的相關(guān)資料,需要的朋友可以參考下2022-05-05

