<script setup>
import { watch, reactive, ref } from 'vue'
const obj = reactive({ count: 1 });
watch(obj, (newVal, oldVal) => {
console.log(newVal, newVal.count, oldVal, oldVal.count, newVal === oldVal);
});
</script>
<template>
<h1 @click="obj.count++">{{ obj.count }}</h1>
</template>
在这个示例中,obj 是一个通过 reactive 创建的响应式对象。watch 监听的是整个 obj 对象。
newVal 和 oldVal:由于 obj 是一个对象,newVal 和 oldVal 都是对同一个对象的引用。即使 obj 的属性发生了变化,obj 本身的引用并没有改变。
newVal === oldVal:由于 newVal 和 oldVal 都是对同一个对象的引用,因此 newVal === oldVal 的结果是 true。
<script setup>
import { computed, watch, ref } from 'vue'
const arr = ref([{ count: 1 }]);
const newArr = computed(() => {
const memoArr = [];
memoArr.push({ count: arr.value[0].count});
return memoArr;
})
watch(newArr, (newVal, oldVal) => {
console.log(newVal, oldVal, newVal === oldVal);
});
</script>
<template>
<h1 @click="arr[0].count++">{{ arr[0].count }}</h1>
</template>
在这个示例中,newArr 是一个通过 computed 计算出来的值,它是一个数组。watch 监听的是 newArr 这个计算属性。
newVal 和 oldVal:每次 arr[0].count 发生变化时,newArr 会重新计算,返回一个新的数组。虽然数组的内容可能相同,但每次返回的数组都是一个新的引用。
newVal === oldVal:由于每次 newArr 计算返回的都是一个新的数组引用,newVal 和 oldVal 是不同的引用,因此 newVal === oldVal 的结果是 false。
对象或数组的引用:如果你监听的是一个对象或数组,newVal 和 oldVal 通常是同一个引用(如示例一),因此 newVal === oldVal 为 true。
计算属性返回新引用:如果你监听的是一个计算属性,且计算属性返回的是一个新的对象或数组(如示例二),那么 newVal 和 oldVal 会是不同的引用,因此 newVal === oldVal 为 false。
理解这一点对于在 Vue 中正确处理 watch 的回调逻辑非常重要,尤其是在处理复杂对象或数组时。