Vue3中 watch、watchEffect 详解
Vue3中 watch、watchEffect 详解
1. watch 的使用
监听 ref 定义的响应式数据
<template>
<div>
<div>值:{{count}}</div>
<button @click="add">改变值</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup(){
const count = ref(0);
const add = () => {
count.value ++
};
watch(count,(newVal,oldVal) => {
console.log('值改变了',newVal,oldVal)
})
return {
count,
add,
}
}
}
</script>
监听 reactive 定义的响应式数据
<template>
<div>
<div>{{obj.name}}</div>
<div>{{obj.age}}</div>
<button @click="changeName">改变值</button>
</div>
</template>
<script>
import { reactive, watch } from 'vue';
export default {
setup(){
const obj = reactive({
name:'zs',
age:14
});
const changeName = () => {
obj.name = 'ls';
};
watch(obj,(newVal,oldVal) => {
console.log('值改变了',newVal,oldVal)
})
return {
obj,
changeName,
}
}
}
</script>
监听多个响应式数据数据
<template>
<div>
<div>{{obj.name}}</div>
<div>{{obj.age}}</div>
<div>{{count}}</div>
<button @click="changeName">改变值</button>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue';
export default {
setup(){
const count = ref(0);
const obj = reactive({
name:'zs',
age:14
});
const changeName = () => {
obj.name = 'ls';
};
watch([count,obj],() => {
console.log('监听的多个数据改变了')
})
return {
obj,
count,
changeName,
}
}
}
</script>
监听对象中某个属性的变化
<template>
<div>
<div>{{obj.name}}</div>
<div>{{obj.age}}</div>
<button @click="changeName">改变值</button>
</div>
</template>
<script>
import { reactive, watch } from 'vue';
export default {
setup(){
const obj = reactive({
name:'zs',
age:14
});
const changeName = () => {
obj.name = 'ls';
};
watch(() => obj.name,() => {
console.log('监听的obj.name改变了')
})
return {
obj,
changeName,
}
}
}
</script>
深度监听(deep)、默认执行(immediate)
<template>
<div>
<div>{{obj.brand.name}}</div>
<button @click="changeBrandName">改变值</button>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue';
export default {
setup(){
const obj = reactive({
name:'zs',
age:14,
brand:{
id:1,
name:'宝马'
}
});
const changeBrandName = () => {
obj.brand.name = '奔驰';
};
watch(() => obj.brand,() => {
console.log('监听的obj.brand.name改变了')
},{
deep:true,
immediate:true,
})
return {
obj,
changeBrandName,
}
}
}
</script>
2. watchEffect 的使用
watchEffect 也是一个帧听器,是一个副作用函数。 它会监听引用数据类型的所有属性,不需要具体到某个属性,一旦运行就会立即监听,组件卸载的时候会停止监听。
<template>
<div>
<input type="text" v-model="obj.name">
</div>
</template>
<script>
import { reactive, watchEffect } from 'vue';
export default {
setup(){
let obj = reactive({
name:'zs'
});
watchEffect(() => {
console.log('name:',obj.name)
})
return {
obj
}
}
}
</script>
停止侦听
当 watchEffect 在组件的 setup() 函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。 在一些情况下,也可以显式调用返回值以停止侦听:
<template>
<div>
<input type="text" v-model="obj.name">
<button @click="stopWatchEffect">停止监听</button>
</div>
</template>
<script>
import { reactive, watchEffect } from 'vue';
export default {
setup(){
let obj = reactive({
name:'zs'
});
const stop = watchEffect(() => {
console.log('name:',obj.name)
})
const stopWatchEffect = () => {
console.log('停止监听')
stop();
}
return {
obj,
stopWatchEffect,
}
}
}
</script>
3. 总结
watch 特点
watch 监听函数可以添加配置项,也可以配置为空,配置项为空的情况下,watch的特点为:
- 有惰性:运行的时候,不会立即执行;
- 更加具体:需要添加监听的属性;
- 可访问属性之前的值:回调函数内会返回最新值和修改之前的值;
- 可配置:配置项可补充 watch 特点上的不足: immediate:配置 watch 属性是否立即执行,值为 true 时,一旦运行就会立即执行,值为 false 时,保持惰性。 deep:配置 watch 是否深度监听,值为 true 时,可以监听对象所有属性,值为 false 时保持更加具体特性,必须指定到具体的属性上。
watchEffect 特点
- 非惰性:一旦运行就会立即执行;
- 更加抽象:使用时不需要具体指定监听的谁,回调函数内直接使用就可以;
- 不可访问之前的值:只能访问当前最新的值,访问不到修改之前的值;
作者:明天也要努力
链接:https://juejin.cn/post/7092412488725037087
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Vue 3 watch增加了同时监听多个变量的能力,用数组表达要监听的变量。回调参数是这种结构:[newR, newS, newT], [oldR, oldS, oldT],不要理解成其他错误的结构
- 被监听的变量必须是:A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.也就是说,可以是getter/effect函数、ref、Proxy以及它们的数组。绝对不可以是纯对象或基本数据。
- Vue 3的深度监听还有没有?当然有,而且默认就是,无需声明。当然,前提是深层 property 也是响应式的。如果深层 property 无响应式,那么即便写上 { deep: true } 也没用。
watch() 总共接收三个参数
第一个参数
是需要被监听的数据源
。这个来源必须是以下几种:
- 一个
getter 函数
,返回一个值 - 一个
ref()
定义的响应式数据 - 一个
reactive()
定义的响应式数据 - 以及由
以上类型的值组成的数组
第二个参数
是在监听的数据源发生变化时要调用的
回调函数
。这个回调函数接受三个
参数:新值(newValue)、旧值(oldValue)
,以及一个用于注册副作用清理的回调函数
。该回调函数
会在副作用下一次重新执行前
调用,可以用来清除无效的副作用,例如等待中的异步请求。
watch(data, (newValue, OldValue, onCleanup) => {
console.log("数据变化了", `新值是:${newValue}`, `旧值是${OldValue}`);
onCleanup(() => {
console.log("清除副作用");
});
});
多个来源时
,回调函数接受两个数组,分别对应来源数组中的新值和旧值
。watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
第三个参数是一个可选参数(options 配置对象),支持以下这些配置选项:
immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined
deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。参考深层监听器
flush:调整回调函数的刷新时机。参考回调刷新的时机以及watchEffect()
onTrack / onTrigger:调试侦听器的依赖。参考侦听器调试
once:回调函数只会运行一次。侦听器将在回调函数首次运行后自动停止。【 3.4+ 版本特性 】
interface WatchOptions extends WatchEffectOptions {
immediate?: boolean // 默认:false
deep?: boolean // 默认:false
flush?: 'pre' | 'post' | 'sync' // 默认:'pre'
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
once?: boolean // 默认:false (3.4+)
}