Vue3监视属性和watchEffect
- 与Vue2.x中的watch配置功能一致
- 两个小坑:
- 监视reactive定义的响应式数据时: oldValue无法正确获取,默认开启了深度监视(deep配置失效)
- 监视reactive定义的响应式数据中某个属性时: deep配置有效
1. 监视ref定义的数据
js
// 情况一:监视ref所定义的一个响应式数据, deep: true没必要,ref里面都是基本类型数据
/* watch(sum, (newValue, oldValue) => {
console.log('sum变了', newValue, oldValue);
}, {immediate:true, deep: true}) */
// 情况二:监视ref所定义的多个响应式数据, immediate为true表示立即监视
watch([sum, msg], (newValue, oldValue) => {
console.log('sum变了', newValue, oldValue);
}, {immediate:true})
运行结果:
js
let person = ref({
name: 'jack',
age: 33
})
watch(person.value, (newValue, oldValue) => {
console.log('person变了', newValue, oldValue);
}, {immediate:true})
为何是person.value不是person呢? 因为ref实例只能检测当前表面的值(但是属性变了,实例对象的指针不变,所以不能监视到),也就是对象数据内部的属性无法监视,而person.value是一个Proxy对象(和reactive处理的对象类型一样),所以可以监视内部属性, 而监视person.value就是监视person, 因为ref处理对象就是将对象reactive处理然后包了一层ref 或者调整这样子可以监视所有属性:
js
watch(person.value, (newValue, oldValue) => {
console.log('person变了', newValue, oldValue);
}, {deep:true})
2. 监视reactive定义的数据
js
let person = reactive({
name: 'jack',
age: 33
})
/* 情况三:监视reactive所定义的一个响应式数据, */
watch(person, (newValue, oldValue) => {
console.log('person变了', newValue, oldValue);
}, {immediate:true})
运行结果: 对于reactive定义的数据不开启深度监视:默认深度监视为true
js
let person = reactive({
name: 'jack',
age: 33,
job:{
j1:{
salary: 20
}
}
})
watch(person, (newValue, oldValue) => {
console.log('person变了', newValue, oldValue);
}, {immediate:true})
手动将deep:false, 深度监视对象将无效,比如监视多层级薪资job.j1.salary属性
3. 监视对象的一个属性
3.1 如果监视对象的一个属性:
比如监视person.age
js
/* 监视reactive所定义的一个响应式对象的属性 */
watch(person.age, (newValue, oldValue) => {
console.log('person的age变了', newValue, oldValue);
})
运行提示警告,并且监视无效 需要更改监视代码:
js
/* 情况五:监视reactive所定义的一个响应式对象的属性,
属性需要是一个函数,不能直接xx.xx */
watch(()=>person.age, (newValue, oldValue) => {
console.log('person的age变了', newValue, oldValue);
})
3.2 监视多个属性的变化:
js
/* 情况六:监视reactive所定义的一个响应式对象的多个属性,
属性需要是一个函数,不能直接xx.xx */
watch([()=>person.age, ()=>person.name], (newValue, oldValue) => {
console.log('person的age或name变了', newValue, oldValue);
})
3.3 监视多层属性的变化
传入一个函数,同时需要开启deep:true
js
/* 情况六:监视reactive所定义的一个响应式对象的多层次属性,
属性需要是一个函数,不能直接xx.xx, */
watch([()=>person.job], (newValue, oldValue) => {
console.log('person的age,name变了', newValue, oldValue);
}, {deep:true})
3. watchEffect函数
- watch的套路是:既要指明监视的属性,也要指明监视的回调
- watchEffect的套路是: 不用指明监视的那个属性,监视的回调中用到那个属性,那就监视那个属性
- watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
js
// watchEffect所指定的回调中用到的数据只要发生变化, 则直接重新执行回调
watchEffect(()=>{
const x1 = sum.value
const x2 = person.value
console.log('watchEffect配置的回调执行了')
})