理解笔记

首先需要理解watch和deep的重要概念,详见【Vue巨坑】当 watch 和 deep: true 相遇:一场由“newVal === oldVal”引发的血案

ref和reactive不一样

  • 不设置deep的情况下(默认deep: false,但reactive不太一样是特例),在watch的第一个参数中直接放一个ref,只能监听到第一层的变化(如ref.value的变化),修改ref.value.aref.value.a.b不会触发回调执行;而放一个reactive则能监听到任何一层,是深度的,默认效果和设置了deep: true是一样的,如果显式设置了deep: false,那么reactive的深层也监听不到了,只能监听到reactive.a的变化。
  • 在设置deep: true的情况下ref和reactive效果一样,都能监听到深层的变化(如xx.a.b的变化)
  • 容易出现误区的地方是(重点理解):
    • 官网文档说如果给ref赋一个对象作为值,那么会给这个对象包一层reactive来实现深层响应性。所以把ref.value放到watch监听中的效果等同于放了一个reactive。但在<template></template>中,ref.a.b(其实ref.a同理)也能响应式更新(在watch中,监听ref无法监听到ref.a.b的变化,但其实这个时候相当于设置了() => ref.value.a.b,即在template中使用ref.xx.xx默认等效于watch中的() => ref.value.xx.xx)。
    • 假如说声明一个const obj = ref({ a: { b: 1 } }),那么在不设置deep的情况下,在watch的第一个参数中放obj,那么只能监听到obj.value,无法监听到obj.value.aobj.value.a.b的变化;放obj.value则可以监听到obj.value.aobj.value.a.b的变化。在<template></template中直接写obj.a.b却可以响应式更新。(本质是对于ref而言,只能监听到ref.value的值的变化;而reactive默认深层监听,可以监听到reactive.a.b

举例

如下demo片段,obj.a.bobj.c<template></template>中都能响应式更新

<script setup>
import { ref } from 'vue'

const obj = ref({
  a: {
    b: 1
  },
  c: 1
})

setInterval(() => {
  obj.value.a.b++;
  // obj.value.c++;
}, 300);

</script>

<template>
  <h1>{{ obj.a.b }}</h1>
  <!-- <h1>{{ obj.c }}</h1> -->
</template>

另一个例子,需要重点理解一个易错点是:

watch中监听ref(未设置deep时),改变ref.value.a是不会触发回调执行的!!!只有改变ref.value才会触发,即使ref.value是个reactive对象。

<script setup>
import { ref, watch } from 'vue'

const obj = ref({
  a: {
    b: 1
  },
  c: 1
});

const numA = ref(0);
const numB = ref(0);

setInterval(() => {
  // obj.value.a.b++;
  obj.value.c++;
}, 300);

// obj 是个 ref, 默认效果是 deep: false, 只能监听到 ref.value 本身的变化
// [易错点!!!] 即只有给 ref.value = {} 一个新地址的时候才能触发回调执行
watch(obj, () => {
  numA.value = numA.value + 1;
});

// obj.value 是个 reactive, 默认深层, 除非显式设置 deep: false
watch(obj.value, () => {
  numB.value = numB.value + 1;
});

</script>

<template>
  <h1>{{ obj.a.b }}</h1>
  <!-- <h1>{{ obj.c }}</h1> -->
  <div>numA不会变: {{ numA }}</div>
  <div>numB会变: {{ numB }}</div>
</template>

A Student on the way to full stack of Web3.