Vue3中watch和watchEffect的區(qū)別及使用技巧總結(jié)
詳細(xì)講解Vue 3 組合式 API 中watch和watchEffect的核心區(qū)別,以及它們的實際使用技巧,以便在開發(fā)中根據(jù)場景正確選擇合適的偵聽器。
一、先明確兩者的核心定位
在 Vue 3 組合式 API 中,watch和watchEffect都是用于監(jiān)聽響應(yīng)式數(shù)據(jù)變化并執(zhí)行副作用的工具,但設(shè)計理念和使用場景有明顯區(qū)別:
watch:顯式監(jiān)聽指定的響應(yīng)式數(shù)據(jù)源,惰性執(zhí)行(默認(rèn)),支持訪問新舊值,控制力更強。watchEffect:隱式監(jiān)聽函數(shù)內(nèi)用到的所有響應(yīng)式數(shù)據(jù)源,立即執(zhí)行(默認(rèn)),自動追蹤依賴,寫法更簡潔。
二、核心區(qū)別對比(表格 + 示例)
| 對比維度 | watch | watchEffect |
|---|---|---|
| 依賴追蹤方式 | 顯式指定監(jiān)聽源(需明確告訴要監(jiān)聽什么) | 隱式追蹤(自動收集函數(shù)內(nèi)用到的響應(yīng)式數(shù)據(jù)) |
| 執(zhí)行時機 | 默認(rèn)懶執(zhí)行(僅當(dāng)監(jiān)聽源變化時執(zhí)行) | 默認(rèn)立即執(zhí)行(組件掛載時先執(zhí)行一次,再監(jiān)聽變化) |
| 新舊值訪問 | 支持(回調(diào)函數(shù)接收新值、舊值參數(shù)) | 不支持(只能訪問當(dāng)前最新值) |
| 監(jiān)聽源類型 | 可監(jiān)聽單個值、多個值、對象屬性、計算屬性等 | 只能監(jiān)聽函數(shù)內(nèi)直接使用的響應(yīng)式數(shù)據(jù) |
| 停止監(jiān)聽 | 返回停止函數(shù),或依賴組件卸載自動停止 | 同左(返回停止函數(shù),組件卸載自動停止) |
| 清除副作用 | 需通過onInvalidate回調(diào)(Vue 3.2 + 推薦) | 同左(回調(diào)函數(shù)接收onInvalidate參數(shù)) |
1. 依賴追蹤方式對比(最核心區(qū)別)
watch:顯式指定監(jiān)聽源
必須明確告訴watch要監(jiān)聽哪個 / 哪些響應(yīng)式數(shù)據(jù),未指定的不會被追蹤:
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('Vue')
// 顯式監(jiān)聽 count,name 變化不會觸發(fā)此 watch
watch(count, (newVal, oldVal) => {
console.log(`count從${oldVal}變成${newVal}`)
})
// 顯式監(jiān)聽多個源(數(shù)組形式)
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
console.log(`count變化:${oldCount}→${newCount},name變化:${oldName}→${newName}`)
})
</script>
watchEffect:隱式追蹤依賴
無需指定監(jiān)聽源,函數(shù)內(nèi)用到的所有響應(yīng)式數(shù)據(jù)都會被自動追蹤:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
const name = ref('Vue')
// 自動追蹤 count 和 name(函數(shù)內(nèi)用到了這兩個響應(yīng)式數(shù)據(jù))
watchEffect(() => {
console.log(`當(dāng)前count:${count.value},當(dāng)前name:${name.value}`)
})
// 首次執(zhí)行輸出:當(dāng)前count:0,當(dāng)前name:Vue(立即執(zhí)行特性)
// 當(dāng)count或name變化時,會重新執(zhí)行
</script>
2. 執(zhí)行時機對比
watch:默認(rèn)懶執(zhí)行
只有監(jiān)聽源發(fā)生變化時才會執(zhí)行,組件掛載時不會主動執(zhí)行:
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
// 組件掛載時不會執(zhí)行,只有 count 變化時才執(zhí)行
watch(count, (newVal) => {
console.log(`count變化了:${newVal}`)
})
// 若需要立即執(zhí)行,需手動設(shè)置 immediate: true
watch(count, (newVal) => {
console.log(`count(立即執(zhí)行):${newVal}`)
}, { immediate: true }) // 組件掛載時執(zhí)行一次,之后 count 變化再執(zhí)行
</script>
watchEffect:默認(rèn)立即執(zhí)行
組件掛載時會先執(zhí)行一次(用于收集依賴),之后依賴變化時再執(zhí)行:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
// 組件掛載時立即執(zhí)行一次,之后 count 變化時再執(zhí)行
watchEffect(() => {
console.log(`count:${count.value}`)
})
// 輸出:count:0(掛載時)→ count:1(當(dāng)count++時)
</script>
3. 新舊值訪問對比
watch:支持訪問新舊值
回調(diào)函數(shù)的第一個參數(shù)是新值,第二個參數(shù)是舊值(引用類型需注意淺對比):
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`舊值:${oldVal},新值:${newVal}`) // 例如:舊值:0,新值:1
})
// 監(jiān)聽對象(需注意:默認(rèn)是淺監(jiān)聽,對象內(nèi)部屬性變化需開啟 deep: true)
const user = ref({ name: 'Vue', age: 3 })
watch(user, (newUser, oldUser) => {
console.log('user變化了', newUser, oldUser)
}, { deep: true }) // 深度監(jiān)聽對象內(nèi)部屬性
</script>
watchEffect:不支持訪問舊值
只能訪問當(dāng)前最新的響應(yīng)式數(shù)據(jù),無法獲取變化前的值:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
watchEffect(() => {
// 只能拿到當(dāng)前值,拿不到變化前的舊值
console.log(`當(dāng)前count:${count.value}`)
})
</script>
三、使用技巧與場景選擇
1. 什么時候用watch?
- 需要訪問新舊值時(如對比變化前后的數(shù)據(jù));
- 需要明確控制監(jiān)聽源(只監(jiān)聽特定數(shù)據(jù),避免無關(guān)依賴觸發(fā));
- 需要延遲執(zhí)行(如使用
flush: 'post'在 DOM 更新后執(zhí)行); - 需要深度監(jiān)聽對象 / 數(shù)組且需要精細(xì)控制時;
- 需要懶執(zhí)行(僅在數(shù)據(jù)變化時執(zhí)行,避免初始化開銷)。
實用技巧:
監(jiān)聽對象單個屬性:用函數(shù)返回具體屬性(避免深度監(jiān)聽整個對象,提升性能):
<script setup> import { ref, watch } from 'vue' const user = ref({ name: 'Vue', age: 3 }) // 只監(jiān)聽 user.name,無需深度監(jiān)聽整個對象 watch(() => user.value.name, (newName) => { console.log(`用戶名變化:${newName}`) }) </script>延遲執(zhí)行(DOM 更新后):使用
flush: 'post':watch(count, () => { // 此時DOM已經(jīng)更新,可以獲取更新后的DOM元素 console.log(document.getElementById('count').innerText) }, { flush: 'post' })
2. 什么時候用watchEffect?
- 副作用依賴多個響應(yīng)式數(shù)據(jù),且無需區(qū)分哪個變化(自動追蹤所有用到的);
- 需要立即執(zhí)行副作用(如初始化時請求數(shù)據(jù),之后依賴變化重新請求);
- 不需要訪問舊值,只關(guān)注當(dāng)前最新狀態(tài);
- 寫法簡潔優(yōu)先(減少代碼量)。
實用技巧:
清除副作用(如取消請求、清除定時器):使用
onInvalidate回調(diào)(組件卸載或副作用重新執(zhí)行前觸發(fā)):<script setup> import { ref, watchEffect } from 'vue' import axios from 'axios' const id = ref(1) watchEffect((onInvalidate) => { // 發(fā)起請求 const request = axios.get(`/api/data/${id.value}`) // 清除函數(shù):組件卸載或 id 變化時觸發(fā) onInvalidate(() => { request.cancel() // 取消請求 }) }) </script>延遲執(zhí)行(同 watch):使用
flush: 'post':watchEffect(() => { // DOM更新后執(zhí)行 console.log(document.getElementById('count').innerText) }, { flush: 'post' })
3. 共同技巧:停止監(jiān)聽
watch和watchEffect都返回一個停止函數(shù),調(diào)用后會停止監(jiān)聽(組件卸載時會自動停止,無需手動調(diào)用):
<script setup>
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
// watch 停止監(jiān)聽
const stopWatch = watch(count, (newVal) => {
console.log(`count:${newVal}`)
})
// watchEffect 停止監(jiān)聽
const stopWatchEffect = watchEffect(() => {
console.log(`count:${count.value}`)
})
// 手動停止監(jiān)聽(如某個條件滿足時)
const stopAll = () => {
stopWatch()
stopWatchEffect()
}
</script>
總結(jié)
核心區(qū)別
- 依賴追蹤:
watch顯式指定源,watchEffect隱式追蹤; - 執(zhí)行時機:
watch默認(rèn)懶執(zhí)行,watchEffect默認(rèn)立即執(zhí)行; - 新舊值:
watch支持訪問新舊值,watchEffect不支持。
場景選擇
- 需舊值、明確監(jiān)聽源、精細(xì)控制 → 用
watch; - 多依賴、立即執(zhí)行、簡潔優(yōu)先 → 用
watchEffect。
關(guān)鍵技巧
watch監(jiān)聽對象單個屬性時,用函數(shù)返回(避免深度監(jiān)聽);watchEffect需清除副作用時,使用onInvalidate;- 兩者都可通過返回的停止函數(shù)手動停止監(jiān)聽,組件卸載時自動停止。
到此這篇關(guān)于Vue3中watch和watchEffect的區(qū)別及使用技巧總結(jié)的文章就介紹到這了,更多相關(guān)Vue3 watch和watchEffect使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue3中Watch、Watcheffect、Computed的使用和區(qū)別解析
- vue3 watch和watchEffect的使用以及有哪些區(qū)別
- Vue3.0監(jiān)聽器watch與watchEffect詳解
- vue3中的watch和watchEffect實例詳解
- 淺談Vue3中watchEffect的具體用法
- Vue3?中?watch?與?watchEffect?區(qū)別及用法小結(jié)
- 一文搞懂Vue3中watchEffect偵聽器的使用
- VUE3中watch和watchEffect的用法詳解
- Vue3中watchEffect和watch的基礎(chǔ)應(yīng)用詳解
- Vue3中的?computed,watch,watchEffect的使用方法
相關(guān)文章
vue使用advanced-mark.js實現(xiàn)高亮文字效果
在日常項目中我們往往會有搜索高亮的需求,下面這篇文章主要介紹了vue使用advanced-mark.js實現(xiàn)高亮文字效果的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-08-08
vue引入微信sdk 實現(xiàn)分享朋友圈獲取地理位置功能
這篇文章主要介紹了h5 vue引入微信sdk 實現(xiàn)分享朋友圈,分享給朋友,獲取地理位置功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07
vue計算屬性無法監(jiān)聽到數(shù)組內(nèi)部變化的解決方案
今天小編就為大家分享一篇vue計算屬性無法監(jiān)聽到數(shù)組內(nèi)部變化的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11

