目录
如何使用 watch ?
如何在首次监听后,自动取消 watch 监听?
如果需要跟踪多个响应式变量,有什么好的解决方案吗?
watchEffect VS watch
是否需要指手动传入依赖
是否为惰性的
每次监听依赖项时 返回的值
watchEffect VS computed
如何使用 watchEffect ?
使用 onInvalidate() 清除 watchEffect 副作用
使用 watchEffect 返回的 stop 方法,停止 watchEffect 监听
使用 flush 修改 watchEffect 监听的时机
Vue Options API 提供了一个 watch 选项
export default {
data () {
return {
title: 'Vue2'
}
},
watch: {
// Watcher
}
}
watch: {
title: {
handler: (newTitle, oldTitle) => {
console.log("Title changed from " + oldTitle + " to " + newTitle);
},
immediate: true,
},
},
适用场景:
调用 watch 自身,可以实现此需求
/**
* 监听 vuex 里开发者配置改变
*/
const watchInitData = watch(
() => store.state[VuexModule.ApplicationLibDevelopment],
async (newVal) => {
// 页面初始化
initPage();
// 调用 watch 本身,可以实现取消监听
watchInitData();
},
{ deep: true },
);
在 Vue Options API(Vue2)中,可以创建多个 watch 观察者
在 Composition API(Vue3)中,可以创建多个 watchEffect 观察者;也可以只创建一个 watchEffect,但在他的回调函数中,写上所有要监听的值
watch —— 既要指明监视的属性,也要指明监视的回调【需要手动传入依赖】
watchEffect —— 不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性【不需要手动传入依赖,会从回调函数中自动获取】
watch 是惰性的 —— 仅当依赖项更改时,才会触发;可以为 watch 传递一个 immediate 属性,使其在初始化时运行
watchEffect 是非惰性的 —— 在创建组件后立即运行,同时,在方法的任何依赖项发生更改时运行
wach —— 每次监听,都会返回新旧值
watchEffect —— 每次监听,只会返回最新的值;只有在页面初始化时,才能拿到一次旧值
watchEffect 和 watch 一样,都有点像 computed
由第二点可得:在挂载 DOM 之前,尽量不要尝试访问 DOM,防止产生不必要的监听
import { ref, watchEffect } from 'vue'
export default {
setup () {
const userID = ref(233)
watchEffect(() => console.log('userID: ' + userID.value))
setTimeout(() => {
userID.value = 666
}, 500)
return {
userID
}
}
}
// 打印结果
userID: 233
userID: 666
也可以在组件中,使用 watchEffect 结合 props 进行使用
export default {
props: {
movieID: String,
},
setup(props) {
watchEffect(() => console.log(props.movieID))
},
}
每当 watchEffect 监听到了依赖项变化时,就执行一个异步请求;
但是在异步请求完成之前,依赖项又发生了变化……
如何避免再一次发请求?
export default {
setup() {
watchEffect(onInvalidate => {
// 异步请求
const apiCall = someAsyncMethod(props.songID)
onInvalidate(() => {
// 取消异步请求
apiCall.cancel()
})
})
}
}
可以手动停止 watchEffect 监听
试想一下,如果你想观察一个依赖项,直到他变成某个值,就不希望继续监听了
继续监听属于浪费资源了,如何实现手动停止 watchEffect 监听?
watchEffect 返回了 stop 方法,调用它,可以手动停止 watchEffect 监听
export default {
setup (props) {
let stopWatcher = watchEffect(() => console.log(props.movieID))
stopWatcher()
}
}
watchEffect 默认在组件加载好之前,就会调用一次监听,举个栗子:
const state = reactive({
test: {
myName: '',
}
});
state.test.myName = 'Lyrelion'
watchEffect(() => {
console.log('名字被修改了', state.test.myName );
})
/**
* 打印结果(在组件更新前,watchEffect 就执行了一次监听,所以会打印两次)
* 名字被修改了
* 名字被修改了 Lyrelion
*/
如果在组件加载好之前,我不想执行监听呢?也就是说,修改 watchEffect 监听时机
可以通过修改 watchEffect 中的 flush 属性,指定监听时机
flush 有以下三种可设置项:
综上所述,为了在组件加载好之前,不执行监听,可以这么写
const state = reactive({
test: {
myName: '',
}
});
state.test.myName = 'Lyrelion'
watchEffect(() => {
console.log('名字被修改了', state.test.myName );
}, {
flush: 'post'
})
/**
* 打印结果(在组件更新前,watchEffect 就执行了一次监听,所以会打印两次)
* 名字被修改了 Lyrelion
*/
补充一篇写的不错的文章
VUE3中watch与watchEffect —— 全网最详细系列_海底烧烤店ai的博客-CSDN博客_watch和watcheffectVUE3——watch与watchEffect详解一、 watchEffect1. 停止监听2. 更改监听时机(更改副作用刷新时机)3. 清除副作用4. 侦听器调试一、watch1. 监听单一源2. 监听多个源3. 侦听响应式对象4. 深度监听5. 立即执行在讲watch之前,我们先来看看watchEffect一、 watchEffect立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。watchEffect的一些特点:不需要手动传入依赖(不用指定监听对象)无https://blog.csdn.net/m0_51969330/article/details/123673334?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-123673334-blog-112723178.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-123673334-blog-112723178.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=2