这是我参与11月更文挑战的第2天,活动详情查看:11月更文挑战
watch基本介绍
watch监听某个属性的变化,一旦发生变化,就会触发对应的回调函数执行,在里面进行一些具体的操作,从而达到事件监听的效果。里面有三个参数,下面让我们一起来学习一下。
第一个参数是:选择要监听的属性。
第二个参数是:设置的回调函数。即监听到变化时应该执行的函数 。
第三个参数是:可以设置deep (深度监听) 其值为true和false。还可以设置immediate (是否以当前值执行回调函数) 其值为true和false。
watch使用
1.监听ref定义的一个响应式数据
import { watch, ref } from 'vue'
setup() {
let mes = ref('会好的')
//第一种情况 监听ref定义的一个响应式数据
watch(mes, (qian, hou) => {
console.log('变化----', qian, hou)
}, {immediate: true})
}
复制代码
2.监听ref定义的多个响应式数据
setup() {
let mes = ref('会好的')
let mess = ref('我是谁')
//第二种情况 监听ref定义的多个响应式数据
watch([mes,mess], (qian, hou) => {
console.log('变化----', qian, hou)
},{immediate:true})
}
复制代码
3.监听reactive定义的属性,会将deep:true强制开启
setup() {
let rea=reactive({
name:'我是谁',
obj:{
salary:20
}
})
//第三种情况 监听reactive定义的属性
watch(rea,(qian,hou)=>{
console.log('rea变化了',qian,hou)
})
}
复制代码
4.监听reactive定义的属性(基本数据)
setup() {
let rea=reactive({
name:'我是谁',
obj:{
salary:20
}
})
//第四种情况 监听reactive定义的属性(基本数据)
watch(()=>rea.name,(qian,hou)=>{
console.log('名称变化===',qian,hou)
})
}
复制代码
5.监听reactive定义的 引用数据 (需要自己开启 deep:true深度监听)
setup() {
let rea=reactive({
name:'我是谁',
obj:{
salary:20
}
})
//第五种情况 监听reactive定义的 (引用数据)
watch([()=>rea.name,()=>rea.obj],(qian,hou)=>{
console.log('监听reactive定义的某一些属性---',qian,hou)
},{deep:true})
}
复制代码
watch存在的一些问题
1.监听reactive定义的响应式数据,会强制开启深度监听(deep:true),无法获取正确的oldvalue(变化前的值)。
2.监听reactive定义的响应式数据中的某个属性(对象形式)时,不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果。
watchEffect基本介绍
Vue3除了watch api,还增加了一个新的watchEffect api,下面我们一起来看看具体的用法。
watchEffect使用
会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。(有点像计算属性)
// 例子来源于(https://v3.vuejs.org/api/computed-watch-api.html#watcheffect)
import { watchEffect, ref } from 'vue'
setup () {
const userID = ref(0)
watchEffect(() => console.log(userID))
setTimeout(() => {
userID.value = 1
}, 1000)
/*
* LOG
* 0
* 1
*/
return {
userID
}
}
复制代码
watchEffect进阶使用
1.停止监听
当 watchEffect
在组件的 setup() 函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。
在一些情况下,也可以显式调用返回值以停止侦听:
const stop = watchEffect(() => {
/* ... */
})
// later
stop()
复制代码
2.清除副作用(onInvalidate)
有时副作用函数会执行一些异步的副作用,这些响应需要在其失效时清除 (即完成之前状态已改变了) 。所以侦听副作用传入的函数可以接收一个 onInvalidate
函数作入参,用来注册清理失效时的回调。当以下情况发生时,这个失效回调会被触发:
- 副作用即将重新执行时
- 侦听器被停止 (如果在
setup()
或生命周期钩子函数中使用了watchEffect
,则在组件卸载时)
watchEffect(onInvalidate => {
const token = performAsyncOperation(id.value)
onInvalidate(() => {
// id has changed or watcher is stopped.
// invalidate previously pending async operation
token.cancel()
})
})
复制代码
我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它,是因为返回值对于异步错误处理很重要。
在执行数据请求时,副作用函数往往是一个异步函数:
const data = ref(null)
watchEffect(async onInvalidate => {
onInvalidate(() => {
/* ... */
}) // 我们在Promise解析之前注册清除函数
data.value = await fetchData(props.id)
})
复制代码
我们知道异步函数都会隐式地返回一个 Promise,但是清理函数必须要在 Promise 被 resolve 之前被注册。另外,Vue 依赖这个返回的 Promise 来自动处理 Promise 链上的潜在错误。
watch注意点
watchEffect
会在 Vue3 开发中大量使用,这里有几个注意点:
1.如果有多个负效应,不要粘合在一起,建议写多个 watchEffect
。
watchEffect(() => {
setTimeout(() => console.log(a.val + 1), 1000);
setTimeout(() => console.log(b.val + 1), 1000);
});
复制代码
这两个 setTimeout 是两个不相关的效应,不需要同时监听 a 和 b,分开写:
watchEffect(() => {
setTimeout(() => console.log(a.val + 1), 1000);
});
watchEffect(() => {
setTimeout(() => console.log(b.val + 1), 1000);
});
复制代码
2.watchEffect
也可以放在其他生命周期函数内
比如你的副作用函数在首次执行时就要调用 DOM,你可以把他放在 onMounted
钩子里:
onMounted(() => {
watchEffect(() => {
// access the DOM or template refs
});
}
复制代码
watch和watchEffect的区别
1.watch可以访问新值和旧值,watchEffect不能访问。
2.watchEffect有副作用,DOM挂载或者更新之前就会触发,需要我们自己去清除副作用。
3.watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行。
4.watch需要指明监听的对象,也需要指明监听的回调。watchEffect不用指明监视哪一个属性,监视的回调函数中用到哪个属性,就监视哪个属性。
总结
以上就是自己对Vue3中监听api的理解,有不对的地方欢迎指出来改正。也希望看完的同学可以给一个免费的赞。以上参考文献出自Vue官方文档