Vue3 的 watch,你們都手動清除過嗎?
前言
大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎(chǔ)是進階的前提是我的初心~
在 Vue3 的響應(yīng)式系統(tǒng)中,watch 是監(jiān)聽數(shù)據(jù)變化的核心 API 之一。隨著 Composition API 的普及,開發(fā)者需要更清晰地理解副作用管理機制。
一、Vue3 的 watch 機制
1.1 基本用法
import { ref, watch } from 'vue'
const count = ref(0)
// 基本監(jiān)聽模式
const stopWatch = watch(count, (newVal, oldVal) => {
console.log(`值從 ${oldVal} 變?yōu)?${newVal}`)
})
// 停止監(jiān)聽
// stopWatch() // 手動調(diào)用停止監(jiān)聽
1.2 自動停止機制
當(dāng)在組件 setup() 中同步創(chuàng)建時,Vue3 會自動關(guān)聯(lián)生命周期:
export default {
setup() {
const count = ref(0)
// 自動綁定組件生命周期
watch(count, (val) => {
console.log('Count changed:', val)
})
return { count }
}
}
組件卸載時,Vue 會自動停止這些監(jiān)聽器,無需手動干預(yù)
二、必須手動清除的 3 種場景
2.1 異步創(chuàng)建的監(jiān)聽器
import { onMounted, onUnmounted } from'vue'
exportdefault {
setup() {
let stopWatch = null
onMounted(() => {
// 異步創(chuàng)建監(jiān)聽器
setTimeout(() => {
stopWatch = watch(/* ... */)
}, 1000)
})
onUnmounted(() => {
if (stopWatch) {
stopWatch() // 必須手動清除
}
})
}
}
關(guān)鍵點:Vue 無法追蹤異步創(chuàng)建的監(jiān)聽器,需要開發(fā)者自行管理
2.2 動態(tài)條件監(jiān)聽
const searchKeyword = ref('')
let searchWatch = null
// 根據(jù)用戶操作動態(tài)創(chuàng)建
function enableSearch() {
searchWatch = watch(searchKeyword, () => {
// 執(zhí)行搜索邏輯
})
}
function disableSearch() {
searchWatch?.() // 主動銷毀
}
典型場景:需要運行時動態(tài)啟用的監(jiān)聽邏輯
2.3 全局狀態(tài)監(jiān)聽
// store.js
import { watch } from'vue'
import store from'./store'
// 全局監(jiān)聽(危險操作!)
let globalWatcher = null
exportfunction initGlobalWatch() {
globalWatcher = watch(
() => store.state.user,
(user) => {
console.log('User changed:', user)
}
)
}
exportfunction cleanupGlobalWatch() {
globalWatcher?.()
}
風(fēng)險提示:全局監(jiān)聽器不會自動銷毀,必須提供顯式清理接口
三、智能管理方案
3.1 自動管理組合式函數(shù)
import { watchEffect, onScopeDispose } from'vue'
exportfunction useAutoCleanWatcher() {
const stop = watchEffect(() => {
// 副作用邏輯
})
// 自動注冊清理
onScopeDispose(() => {
stop()
})
return { stop }
}
優(yōu)勢:利用 onScopeDispose 實現(xiàn)自動清理
3.2 監(jiān)聽器工廠模式
function createSmartWatcher(source, callback) {
const stop = watch(source, callback)
return {
stop,
restart: () => {
stop()
return createSmartWatcher(source, callback)
}
}
}
// 使用示例
const { stop } = createSmartWatcher(value, () => {})
擴展性:封裝重啟功能,增強可維護性