<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
的回调逻辑非常重要,尤其是在处理复杂对象或数组时。