Vue 中 watch 的新旧值问题

老牛浏览 38评论 0发表于

示例一

vue
<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>
9fb6d819-8786-48da-85e7-77359e8b2508

在这个示例中,obj 是一个通过 reactive 创建的响应式对象。watch 监听的是整个 obj 对象。

  • newValoldVal:由于 obj 是一个对象,newValoldVal 都是对同一个对象的引用。即使 obj 的属性发生了变化,obj 本身的引用并没有改变。

  • newVal === oldVal:由于 newValoldVal 都是对同一个对象的引用,因此 newVal === oldVal 的结果是 true

示例二

vue
<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>
a9ad1174-6d35-4774-95c5-6024dde6e021

在这个示例中,newArr 是一个通过 computed 计算出来的值,它是一个数组。watch 监听的是 newArr 这个计算属性。

  • newValoldVal:每次 arr[0].count 发生变化时,newArr 会重新计算,返回一个新的数组。虽然数组的内容可能相同,但每次返回的数组都是一个新的引用。

  • newVal === oldVal:由于每次 newArr 计算返回的都是一个新的数组引用,newValoldVal 是不同的引用,因此 newVal === oldVal 的结果是 false

总结

  • 对象或数组的引用:如果你监听的是一个对象或数组,newValoldVal 通常是同一个引用(如示例一),因此 newVal === oldValtrue

  • 计算属性返回新引用:如果你监听的是一个计算属性,且计算属性返回的是一个新的对象或数组(如示例二),那么 newValoldVal 会是不同的引用,因此 newVal === oldValfalse

理解这一点对于在 Vue 中正确处理 watch 的回调逻辑非常重要,尤其是在处理复杂对象或数组时。

点赞
收藏
暂无评论,快来发表评论吧~
私信
老牛@ilaoniu
老牛,俗称哞哞。单纯的九零后理工小青年。喜欢折腾,爱玩,爱音乐,爱游戏,爱电影,爱旅游...
最后活跃于