一文詳解Vue3中watch的使用方法、寫法及應(yīng)用場景
引言
在 Vue 3 的組合式 API(Composition API)中,watch 是一個(gè)非常核心且強(qiáng)大的工具,用于監(jiān)聽響應(yīng)式數(shù)據(jù)的變化并執(zhí)行相應(yīng)的副作用操作。本文將結(jié)合實(shí)際代碼示例,深入講解 watch 的使用方法、參數(shù)配置(如 deep、immediate)、常見寫法及其應(yīng)用場景。
一、watch 基本用法
Vue 3 中的 watch 函數(shù)用于監(jiān)聽響應(yīng)式引用(ref)、響應(yīng)式對象(reactive)或計(jì)算屬性(computed)的變化。其基本語法如下:
import { watch } from 'vue'
watch(source, callback, options?)- source:要監(jiān)聽的數(shù)據(jù)源,可以是 ref、reactive 對象、getter 函數(shù),或由多個(gè)上述組成的數(shù)組。
- callback:當(dāng)監(jiān)聽的數(shù)據(jù)發(fā)生變化時(shí)觸發(fā)的回調(diào)函數(shù),接收新值和舊值作為參數(shù)。
- options(可選):配置選項(xiàng),如
{ deep: true, immediate: true }。
二、常見寫法與示例分析
1. 監(jiān)聽 ref 或 reactive 對象
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`count 從 ${oldVal} 變?yōu)?${newVal}`)
})對于 reactive 對象,若只監(jiān)聽整個(gè)對象(而非深層屬性),默認(rèn)不會觸發(fā)深層監(jiān)聽:
const user = reactive({ name: 'Alice', age: 25 })
// ? 這樣不會監(jiān)聽到 user.name 的變化!
watch(user, (newVal, oldVal) => {
// 不會觸發(fā)
})此時(shí)需要開啟 deep: true(見下文)。
2. 使用 getter 函數(shù)監(jiān)聽特定屬性(推薦方式)
這是最靈活、最常用的方式,尤其適用于監(jiān)聽 props、route 等非直接 ref 的數(shù)據(jù)。
示例 1:監(jiān)聽 props 中的復(fù)雜對象(如數(shù)組)
watch(
() => props.fileList,
(newFiles, oldFiles) => handleFiles(newFiles, oldFiles),
{ deep: true }
)() => props.fileList:返回一個(gè) getter 函數(shù),確保能正確追蹤依賴。deep: true:因?yàn)?fileList很可能是數(shù)組或?qū)ο?,?nèi)部元素變化不會觸發(fā)淺層監(jiān)聽,必須開啟深度監(jiān)聽。- 回調(diào)函數(shù)接收新舊值,便于做差異處理(如上傳文件列表變更)。
注意:如果 fileList 是一個(gè)數(shù)組,即使你 push 一個(gè)新文件,淺層監(jiān)聽也不會觸發(fā),因?yàn)閿?shù)組引用未變。deep: true 能解決這個(gè)問題。
示例 2:監(jiān)聽路由路徑變化
watch(
() => route.path,
(newPath) => {
activeMenu.value = newPath
}
)route來自vue-router的useRoute(),是一個(gè)響應(yīng)式對象。- 監(jiān)聽
route.path可以在用戶切換頁面時(shí)自動更新高亮菜單項(xiàng)。 - 此處無需
deep,因?yàn)?path是字符串(原始值),變化即觸發(fā)。
三、關(guān)鍵配置選項(xiàng)詳解
1.deep: true—— 深度監(jiān)聽
- 作用:監(jiān)聽對象或數(shù)組內(nèi)部屬性的變化。
- 適用場景:監(jiān)聽嵌套對象、數(shù)組、props 中的復(fù)雜結(jié)構(gòu)。
- 注意:性能開銷較大,僅在必要時(shí)使用。
const form = reactive({
user: { name: '', email: '' }
})
watch(form, (newVal) => {
// 默認(rèn)不觸發(fā)
}, { deep: true }) // 開啟后,user.name 變化也會觸發(fā)對于 ref 包裹的對象,watch(refObj, ..., { deep: true }) 也能深度監(jiān)聽。
2.immediate: true—— 立即執(zhí)行
- 作用:在偵 聽器創(chuàng)建時(shí)立即執(zhí)行一次回調(diào)。
- 適用場景:初始化時(shí)就需要根據(jù)當(dāng)前值執(zhí)行邏輯(如根據(jù)路由加載數(shù)據(jù))。
watch(
() => route.query.id,
(id) => {
if (id) fetchDetail(id)
},
{ immediate: true }
)如果不加 immediate: true,首次進(jìn)入頁面時(shí) id 存在但不會觸發(fā) fetchDetail。
3. 同時(shí)監(jiān)聽多個(gè)源
watch([refA, refB], ([newA, newB], [oldA, oldB]) => {
console.log('A or B changed')
})四、watch vs watchEffect
| 特性 | watch | watchEffect |
|---|---|---|
| 是否需要指定依賴 | ? 需要顯式指定 | ? 自動追蹤 |
| 能否訪問舊值 | ? 可以 | ? 不能 |
| 是否立即執(zhí)行 | 默認(rèn)否(可用 immediate 控制) | ? 總是立即執(zhí)行 |
| 適用場景 | 需要對比新舊值、精確控制依賴 | 初始化 + 自動依賴追蹤 |
通常建議優(yōu)先使用 watch,因?yàn)樗鞔_、可控。
五、最佳實(shí)踐建議
- 監(jiān)聽 props 時(shí),始終使用 getter 寫法:
() => props.xxx - 對對象/數(shù)組變化,記得加
deep: true - 需要初始化執(zhí)行?加
immediate: true - 避免在 watch 中修改被監(jiān)聽的值,可能引發(fā)無限循環(huán)
- 及時(shí)清理副作用(如取消請求),可在回調(diào)中返回清理函數(shù)(類似 useEffect)
watch(someRef, async (id) => {
const cancelToken = axios.CancelToken.source()
try {
await axios.get(`/api/data/${id}`, { cancelToken: cancelToken.token })
} catch (e) {
if (!axios.isCancel(e)) throw e
}
// 返回清理函數(shù)
return () => cancelToken.cancel()
})六、總結(jié)
watch 是 Vue 3 組合式 API 中處理副作用和響應(yīng)式數(shù)據(jù)聯(lián)動的核心工具。通過合理使用 deep、immediate 等選項(xiàng),我們可以精準(zhǔn)控制監(jiān)聽行為,提升應(yīng)用的響應(yīng)性和用戶體驗(yàn)。
以上就是一文詳解Vue3中watch的使用方法、寫法及應(yīng)用場景的詳細(xì)內(nèi)容,更多關(guān)于Vue3 watch使用方法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue使用video標(biāo)簽實(shí)現(xiàn)視頻播放
這篇文章主要為大家詳細(xì)介紹了Vue使用video標(biāo)簽實(shí)現(xiàn)視頻播放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
vue使用openlayers實(shí)現(xiàn)移動點(diǎn)動畫
這篇文章主要為大家詳細(xì)介紹了vue使用openlayers實(shí)現(xiàn)移動點(diǎn)動畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09
從入門到精通詳解Vue如何實(shí)現(xiàn)防止重復(fù)提交
作為經(jīng)歷過大型項(xiàng)目洗禮的前端工程師,小編深知重復(fù)提交問題絕非簡單的按鈕禁用就能解決,今天,就將帶大家構(gòu)建一套生產(chǎn)級的重復(fù)提交防御體系,涵蓋從基礎(chǔ)到架構(gòu)的全套方案2025-06-06
Vue reactive函數(shù)實(shí)現(xiàn)流程詳解
一個(gè)基本類型的數(shù)據(jù),想要變成響應(yīng)式數(shù)據(jù),那么需要通過ref函數(shù)包裹,而如果是一個(gè)對象的話,那么需要使用reactive函數(shù),這篇文章主要介紹了Vue reactive函數(shù)2023-01-01
Vue2.0使用嵌套路由實(shí)現(xiàn)頁面內(nèi)容切換/公用一級菜單控制頁面內(nèi)容切換(推薦)
這篇文章主要介紹了Vue2.0使用嵌套路由實(shí)現(xiàn)頁面內(nèi)容切換/公用一級菜單控制頁面內(nèi)容切換,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
Vue3?$emit用法指南(含選項(xiàng)API、組合API及?setup?語法糖)
這篇文章主要介紹了Vue3?$emit用法指南,使用?emit,我們可以觸發(fā)事件并將數(shù)據(jù)傳遞到組件的層次結(jié)構(gòu)中,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

