目录
watch监听器
-
与Vue2.x中watch配置功能一致;
-
两个小“坑”:
-
监听reactive定义的
响应式数据
,会强制开启深度监听(deep:true),无法获取正确的oldvalue(变化前的值)。 -
监听reactive定义的
响应式数据中的某个属性(对象形式)
时,不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果。
-
Vue2 中的 watch 回顾
- Vue2 中只能有一个 watch 的配置项;
watch: {
// 简单写法
sum(newVal, oldVal) {
console.log("sum的值发生改变", newVal, oldVal);
},
// 复杂写法
sum: {
immediate: true, // 立即监听
deep: true, // 深度监听
handler(newVal, oldVal) {
console.log("sum的值发生改变", newVal, oldVal);
},
},
},
Vue3 中的 watch 函数案例实现
<template>
<h1>一个人的信息</h1>
<h2>当前求和为: {{ sum }}</h2>
<button @click="sum++">点我+1</button>
<hr />
<h2>当前数据: {{ msg }}</h2>
<button @click="msg += '!'">修改msg信息</button>
<hr />
<h2>姓名: {{ person.name }}</h2>
<h2>年龄: {{ person.age }}</h2>
<h2>薪资: {{ person.job.j1.salary }} K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, watch, reactive, watchEffect } from "vue";
export default {
name: "Demo",
setup() {
let sum = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
// watch( 监视的属性, ()=>{ 监视的回调}, { 监视的配置 })
/* 情况1: 监视ref所定义的一个响应式数据 */
watch(sum, (newVal, oldVal) =>{
console.log('sum变了', newVal, oldVal );
})
/* 情况2: 监视ref所定义的多个响应式数据, 在vue3中watch函数可以调用多次 */
watch([sum, msg], (newVal, oldVal) => {
console.log("sum或msg变了", newVal, oldVal);
}, { immediate:true});
/*
情况3: 监听 reactive 所定义的一个响应式数据的全部属性;
1.注意: 此处无法正确的获取oldValue
2.注意: 强制开启深度监听(deep配置无效 { deep:false })
*/
watch(person, (newValue, oldValue) =>{
console.log('person变化了', newValue, oldValue);
},{ deep:false }) // 此处的deep配置是无效的
/* 情况4:监听 reactive 所定义的一个响应式数据中的某个属性 */
watch(() => person.age,(newValue, oldValue) => {
console.log("person属性变化了", newValue, oldValue);
}
);
/* 情况5:监听 reactive 所定义的一个响应式数据中的某些属性 */
watch([() => person.name, () => person.age],(newValue, oldValue) => {
console.log("person属性变化了", newValue, oldValue);
}
);
/* 特殊情况 */
watch(() => person.job,(newValue, oldValue) => {
console.log("person属性变化了", newValue, oldValue);
}, { deep: true} // 此处由于监视的是reactive所定义的对象中属性值是对象, 所以deep配置有效。
);
return {
sum,
msg,
person,
};
},
};
</script>
Vue3 中的 watch 函数 value 的问题
<template>
<h1>一个人的信息</h1>
<h2>当前求和为: {{ sum }}</h2>
<button @click="sum++">点我+1</button>
<hr />
<h2>当前数据: {{ msg }}</h2>
<button @click="msg += '!'">修改msg信息</button>
<hr />
<h2>姓名: {{ person.name }}</h2>
<h2>年龄: {{ person.age }}</h2>
<h2>薪资: {{ person.job.j1.salary }} K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, watch, reactive } from "vue";
export default {
name: "Demo",
setup() {
let sum = ref(0);
let msg = ref("你好啊");
let person = ref({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
/* Vue3中watch函数监听ref响应式数据value问题 */
// 1. watch 不能监听: sum.value, 而是能监听 ref 定义的 RefImpl 的数据结构!
watch(sum, (newVal, oldVal) => {
console.log(`sum的值发生改变`);
});
/*
1.person 是一个 ref 定义的数据, person 的源数据是对象类型;
2.vue3 ref 定义对象的响应式数据,是求助reactive函数生成的;
2.1. 我们 person.value 获取proxy的对象, 直接获取监听(默认是深度监听)
2.2. 设置 deep : true 开启深度监听
*/
watch(person.value, (newVal, oldVal) => {
console.log(`person的值发生改变`);
});
// 不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果
watch(person, (newVal, oldVal) => {
console.log(`person的值发生改变`);
},{ deep: true });
return {
sum,
msg,
person,
};
},
};
</script>
Vue3 中的 watchEffect高级监听器
watchEffect有点像computed:
-
但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
-
而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
-
watchEffect如果监听reactive定义的对象是不起作用的,只能监听对象中的属性。
Vue3 中的 watchEffect函数案例实现
<template>
<h1>一个人的信息</h1>
<h2>当前求和为: {{ sum }}</h2>
<button @click="sum++">点我+1</button>
<hr />
<h2>当前数据: {{ msg }}</h2>
<button @click="msg += '!'">修改msg信息</button>
<hr />
<h2>姓名: {{ person.name }}</h2>
<h2>年龄: {{ person.age }}</h2>
<h2>薪资: {{ person.job.j1.salary }} K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, watch, reactive, watchEffect } from "vue";
export default {
name: "Demo",
setup() {
let sum = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 20,
},
},
});
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect((before) => {
console.log("触发了watchEffect");
console.log(`修改后的值为:${sum.value} ${msg.value} ${person.name}`);
// 默认修改后不执行, 触发修改后优先执行
before(() => {
console.log("先执行的 before 回调");
});
});
return {
sum,
msg,
person,
};
},
};
</script>
小结
- watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行(忽略watch第三个参数的配置,如果修改配置项也可以实现立即执行)
- watch需要传递监听的对象,watchEffect不需要
- watch只能监听响应式数据:ref定义的属性和reactive定义的对象,如果直接监听reactive定义对象中的属性是不允许的(会报警告),除非使用函数转换一下。其实就是官网上说的监听一个getter
- watchEffect如果监听reactive定义的对象是不起作用的,只能监听对象中的属性。