直接上代码,总共测试了下面这些情况(看注释)
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点我+1</button>
<hr />
<h2>当前的信息为:{{ msg }}</h2>
<button @click="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, reactive, watch } from "vue";
export default {
name: "Demo",
setup() {
//数据
let sum = ref(0);
let msg = ref("你好啊");
let person = reactive({
name: "张三",
age: 18,
job: {
j1: {
salary: 3,
},
},
});
//情况一:监视ref所定义的一个响应式数据
watch(
sum,
(newValue, oldValue) => {
console.log("sum变了", newValue, oldValue);
},
{ immediate: true }
);
//情况二:监视ref所定义的多个响应式数据
watch(
[sum, msg],
(newValue, oldValue) => {
console.log("sum或msg变了", newValue, oldValue);
},
{ immediate: true }
);
/*
情况三:监视reactive所定义的一个响应式数据的全部属性
1.注意:此处无法正确的获取oldValue
2.注意:强制开启了深度监视(deep配置无效)
*/
watch(
person,
(newValue, oldValue) => {
console.log("person变化了", newValue, oldValue);
},
{ deep: false }
); //此处的deep配置无效
//情况四:监视reactive所定义的一个响应式数据中的某个属性
// watch(
// () => person.name,
// (newValue, oldValue) => {
// console.log("person的name变化了", newValue, oldValue);
// }
// );
//情况五:监视reactive所定义的一个响应式数据中的某些属性
// watch([() => person.name, () => person.age], (newValue, oldValue) => {
// console.log("person的name或age变化了", newValue, oldValue);
// });
//特殊情况
// watch(
// () => person.job,
// (newValue, oldValue) => {
// console.log("person的job变化了", newValue, oldValue);
// },
// { deep: true }
// ); //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
//返回一个对象(常用)
return {
sum,
msg,
person,
};
},
};
</script>
总结:
- 如果定义了reactive的数据,想去使用watch监听数据改变,则无法正确获取旧值,并且deep属性配置无效,自动强制开启了深层次监听。
- 如果使用 ref 初始化一个对象或者数组类型的数据,会被自动转成reactive的实现方式,生成proxy代理对象。也会变得无法正确取旧值。
- 用任何方式生成的数据,如果接收的变量是一个proxy代理对象,就都会导致watch这个对象时,watch回调里无法正确获取旧值。
所以当大家使用watch监听对象时,如果在不需要使用旧值的情况,可以正常监听对象没关系;但是如果当监听改变函数里面需要用到旧值时,只能监听 对象.xxx属性 的方式才行。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。