作用:监视数据的变化(和 Vue2 中的 watch 作用一致)
特点:Vue3 中的 watch 只能监视以下四种数据:
1.ref 定义的数据。
2.reactive 定义的数据。
3.函数返回一个值(getter 函数)。
4.一个包含上述内容的数组。
watch 监听
⭐情况一
监视【ref】 直接写数据名即可,监视的是其 value 值的改变。
示例:
import { watch, ref } from 'vue';
const count = ref(0);
// 监视 ref 'count' 的变化
watch(count, (newValue, oldValue) => {
console.log(`变化前:${oldValue} 变化后: ${newValue}`);
},{
deep: true, // 深度监听 state 对象内部的变化
immediate: true, // 当设置为 true 时,watch 会在开始监视后立即执行一次回调函数。
flush: 'pre', // 控制副作用(如 DOM 更新)的刷新时机。可以是 'pre' 或 'post',或者一个包含这些值的数组。
onTrack: () => {}, // 依赖项被追踪时调用
onTrigger:() =>{}, // 依赖项变化时调用
computed: true // 计算属性模式
});
⭐情况二
监视【ref】深层要手动开启深度监视
注意:
若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
示例:
import { watch, ref } from 'vue';
const person = ref({ name: 'John', age: 30 });
// 监视 ref 'person' 的深层属性变化
watch(
() => person.value, // 使用函数返回 ref 的 value,以确保每次都是最新的值
(newValue, oldValue) => {
// 回调函数会在 person 对象的属性变化时触发
console.log(`变化前:${oldValue.name} 变化后:${newValue.name}`);
},
{ deep: true } // 开启深度监视
);
在这个例子中:
- person 是一个通过 ref 创建的响应式引用,它包含一个对象,该对象有 name 和 age 属性。
- 使用 watch 函数并传入一个函数,该函数返回 person.value。这样做是因为我们需要监视 person 对象内部属性的变化,而不是 person 这个引用本身。
- 参数 { deep: true } 开启了深度监视,这样 watch 就能够追踪到对象内部属性的变化。
- 当 person 对象的 name 或 age 属性发生变化时,提供的回调函数会被触发。
注意事项
- 当你监视 ref 定义的对象并开启深度监视时,newValue 和 oldValue 将代表对象内部发生变化的属性的新旧值。
- 如果整个 ref 定义的对象被一个新的对象替换,那么 newValue 将是新对象,而 oldValue 将是旧对象。
- 开启深度监视可能会带来性能上的考虑,因为它会增加 Vue 需要追踪的变化的数量。
⭐情况三
监视【reactive】定义的【对象类型】数据,默认开启深度监视(无法关闭)
示例:
import { reactive, watch } from 'vue';
// 使用 reactive 创建一个响应式对象
const person = reactive({
name: 'John',
details: {
age: 30
}
});
// 监视 reactive 对象的 'details.age' 属性
watch(
() => person.details.age,
(newValue, oldValue) => {
console.log(`Age changed from ${oldValue} to ${newValue}`);
}
);
在这个例子中:
- person 是一个使用 reactive 创建的响应式对象,它包含一个名为 details 的属性,该属性本身也是一个对象,包含 age 属性。
- 使用 watch 来监视 person.details.age 属性的变化。由于 reactive 默认进行深度监视,因此不需要额外的 deep 选项即可追踪到 details 对象内部的 age 属性变化。
注意事项
- reactive 创建的响应式对象总是深度监视的,这意味着你无法关闭这个行为。
- 当你使用 watch 来监视 reactive对象的属性时,即使属性是嵌套的,也不需要 deep 选项,因为深度监视是自动应用的。
- 如果 reactive 对象的某个属性也是一个对象,并且你想要监视这个嵌套对象的属性,你可以直接使用 watch,并提供一个返回该嵌套属性的函数。
通过这种方式,Vue 3 的 reactive API 提供了一种直观且强大的方式来创建和管理响应式状态,同时 watch API 允许你监视这些状态的变化,无需担心监视的深度问题。
⭐情况四
监视响应式对象中的某个属性,且该属性是基本类型,要写成函数式
监视响应式对象中的某个属性,且该属性是对象类型,可以直接写,也能写函数,更推荐写函数
⭐结论:监视的要是对象里的属性,那么最好写函数式
⭐注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。
基本类型属性的监视
当监视响应式对象中的基本类型属性时,推荐使用函数式的方式来访问该属性的值。这是因为基本类型的属性不会触发对象的重新分配,所以每次获取的都是最新的值。
示例:
import { watch, reactive } from 'vue';
const person = reactive({ name: 'John' });
// 使用函数式监视响应式对象中的 'name' 属性
watch(
() => person.name,
(newValue, oldValue) => {
console.log(`变化前:${oldValue} 变化后:${newValue}`);
}
);
在这个例子中,我们通过函数 () => person.name 来获取 person 对象的 name 属性的值。每次 watch 触发时,都会调用这个函数以确保获取到最新的 name 值。
对象类型属性的监视
当监视响应式对象中的对象类型属性时,可以直接写属性名,也可以使用函数式。推荐使用函数式,尤其是当你需要监视对象内部属性的变化时。
示例:
const person = reactive({ detail: { address: '123 Main St' } });
// 使用函数式监视 'detail' 对象内部的 'address' 属性
watch(
() => person.detail.address,
(newValue, oldValue) => {
console.log(`变化前: ${oldValue} 变化后:${newValue}`);
},deep: true } // 开启深度监视,以追踪对象内部属性的变化
);
在这个例子中,我们监视的是 person.detail.address。由于 address 是 detail 对象的属性,我们需要开启深度监视 { deep: true } 来确保当 address 发生变化时,watch 能够触发。
我们通过函数 () => person.name 来获取 person 对象的 name 属性的值。每次 watch 触发时,都会调用这个函数以确保获取到最新的 name 值。
⭐情况五:监视上述的多个数据
示例
import { watch, reactive, ref } from 'vue';
// 使用 reactive 创建一个响应式对象
const person = reactive({
name: 'John',
car: 'Toyota'
});
// 使用 ref 创建一个响应式引用
const age = ref(30);
// 监视 person 对象的 'name' 属性和 age 引用
watch([() => person.name, age], (newValues, oldValues) => {
// newValues 和 oldValues 都是数组,分别包含新旧值
console.log(`Name changed to ${newValues[0]}, Age changed to ${newValues[1]}`);
// 如果只想监视 person.car 的变化,可以这样写:
// watch([() => person.car, age], callback, options)
}, { deep: true });
在这个例子中:
- 使用 reactive 创建了一个响应式对象 person,它包含 name 和 car 属性。
- 使用 ref 创建了一个响应式引用age。 使用 watch 来监视 person.name 和 age。
- 这里通过传递一个数组给 watch的第一个参数来实现同时监视多个数据源。数组中的每个元素都是一个返回要监视数据的函数或响应式引用。
- newValues 和oldValues 参数都是数组,它们包含了所有监视数据源的新旧值。数组中每个元素的顺序与 watch 第一个参数中的顺序相对应。
- { deep: true } 表示对 person 对象进行深度监视,这样可以确保当对象内部的属性变化时,也能触发 watch
的回调函数。
注意事项
- 当监视多个响应式数据源时,确保 newValues 和 oldValues 的索引与 watch 第一个参数中数据源的顺序相匹配。
- 使用deep: true 选项可以确保当监视的对象或数组内部发生变化时,也能触发回调函数。