我将创建一个小知识点系列文章,每篇文章只围绕一个很小的知识点展开,阅读成本低,压力小,目的是能够以比较少的时间对一个知识点进行比较扎实的理解和掌握,本篇是该系列的第一篇文章。
本篇文章针对vue官网中的如下一句话进行比较详细的整理总结,希望对大家有帮助。
watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组。
1、监听ref定义的数据
ref可以用于定义任意类型的响应式变量,包含基础类型和引用类型数据,下面分两种情况进行说明。
1.1、ref定义的【基础类型】数据
ref定义的【基础类型】数据本身就是响应式变量,可以直接通过watch方法监听。
const x = ref(0);
watch(x, (newValue) => {
console.log(`x is ${newValue}`)
});
x.value += 2;
1.2、ref定义的【引用类型】数据
如果监听整个变量,则监听的是对象的“地址值”,因为refVar.value是一个对象,而对象是地址的引用,所以当对象中的属性变化的时候由于对象的地址引用不变,则不会触发监听。 如果要监听整个对象的重新赋值,则可以这么监听整个变量,此时newVal是新值的地址引用,oldVal是旧值的地址引用。
const info = ref({
name: 'vue3',
version: '3.0',
});
watch(info, (newValue, oldValue) => {
// 注意:`newValue` 和 `oldValue` 是不相等的
console.log('watch info: ', newValue, oldValue);
});
info.value = {
name: 'vue2',
version: '2.0',
};
如果要监听对象中的属性变化,要手动开启深度监听deep,表示深度监听对象/数组内部变化,注意此时newVal和oldVal是相同的新值,因为是地址引用,它们是同一个对象。
watch(
info,
(newValue, oldValue) => {
console.log('watch info: ', newValue, oldValue)
},
{ deep: true },
)
info.value.version = '3.7'
2、监听reactive定义的数据
因为reactive只能用于创建引用类型的响应式状态数据,所以对其监听的时候watch默认就会开启deep深度监听,不需要再手动设置。
const obj = reactive({ count: 0 })
watch(obj, (newValue, oldValue) => {
// 在嵌套的属性变更时触发
// 注意:`newValue` 此处和 `oldValue` 是相等的
// 因为它们是同一个对象!
})
obj.count++
3、监听getter函数
getter函数可以返回响应式对象的某个属性,用于仅监听该属性的变化的情况。对于仅监听对象中某个属性的情况,推荐使用getter函数的方式,比对整个对象进行深度监听的效率更高。
const info = ref({
name: 'vue3',
version: '3.0',
});
// 提供一个 getter 函数
watch(
() => info.version,
(newValue) => {
console.log(`version is: ${newValue}`)
}
)
也可以返回几个响应式变量的计算结果,类似于计算属性,可以监听该计算结果的变化。
const x = ref(0);
const y = ref(0);
// getter 函数
watch(
() => x.value + y.value,
(sum) => {
console.log(`sum of x + y is: ${sum}`)
}
)
x.value++;
4、监听多个数据源组成的数组
vue3支持同时监听多个数据源,数据源可以是上面三种可监听的数据类型。当多个数据源的变化触发的回调处理相同时,可以使用这种数组的方式同时监听。
const x = ref(0)
const y = ref(0)
watch([x, y], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
总结
实际开发中,监听ref定义的【基础类型】数据,监听reactive定义的响应式对象,和监听对象的某个属性的情况比较常用。但凡要监听一个属性,反手就写一个getter函数。