Skip to content

监视属性

作用

监视数据的变化, 与 Vue2 watch 作用一致

特点

Vue3中的watch只能监视以下四种数据:

  1. ref定义的数据
  2. reactive定义的数据
  3. 函数(getter函数)返回一个值
  4. 一个包含上述内容的数组

使用

Vue3中使用watch的时候, 通常会遇到以下几种情况

情况一

监视ref定义的基本类型数据: 直接写数据名即可, 监视的是其value值的改变

  • 代码示例
vue
<template>
  <div class="person">
    <h1>情况一: 监视 [ref] 定义的 [基本类型] 数据</h1>
    <h2>当前求和为: {{ sum }}</h2>
    <button @click="changeSum">点我sum+1</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { ref, watch } from 'vue'
  // 数据
  let sum = ref(0)
  // 方法
  function changeSum(){
    sum.value += 1
  }

  // 监视情况一: 情况一: 监视 [ref] 定义的 [基本类型] 数据
  const stopWatch = watch(sum, (newValue, oldValue) => {
    console.log('sum变化了', newValue, oldValue)
    if (newValue >= 10){
      stopWatch()
    }
  })
</script>

情况二

监视ref定义的对象类型数据: 直接写数据名, 监视的是对象的地址值, 若想监视对象内部的数据, 要手动开启深度监视

注意

  • 若修改的是ref定义的对象中的属性, newValueoldValue都是新值, 因为它们是同一个对象
  • 若修改整个ref定义的对象, newValue是新值, oldValue是旧值, 因为不是同一个对象了
  • 代码示例
vue
<template>
  <div class="person">
    <h1>情况二: 监视 [ref] 定义的 [对象类型] 数据</h1>
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">修改整个人</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { ref, watch } from 'vue'

  // 数据
  let person = ref({
    name: '张三',
    age: 18
  })

  // 方法
  function changeName() {
    person.value.name += '~'
  }
  function changeAge() {
    person.value.age += 1
  }
  function changePerson() {
    person.value = { name:'李四', age:90 }
  }

  /* 
    监视情况二: 监视 [ref] 定义的 [对象类型] 数据, 监视的是对象的地址值, 若想监视对象内部属性的变化, 需要手动开启深度监视
    watch的第一个参数是: 被监视的数据
    watch的第二个参数是: 监视的回调
    watch的第三个参数是: 配置对象(deep、immediate 等)
  */
  watch(person, (newValue, oldValue) => {
    console.log('person变化了', newValue, oldValue)
  },{ deep: true })
</script>

情况三

监视reactive定义的对象类型数据, 且默认开启了深度监视

  • 代码示例
vue
<template>
  <div class="person">
    <h1>情况三: 监视 [reactive] 定义的 [对象类型] 数据</h1>
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">修改整个人</button>
    <hr />
    <h2>测试: {{ obj.a.b.c }}</h2>
    <button @click="changeTest">修改测试</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { reactive, watch } from 'vue'

  // 数据
  let person = reactive({
    name: '张三',
    age: 18
  })
  let obj = reactive({
    a: {
      b: {
        c: 666
      }
    }
  })

  // 方法
  function changeName() {
    person.name += '~'
  }
  function changeAge() {
    person.age += 1
  }
  function changePerson() {
    Object.assign(person, { name: '李四', age: 80 })
  }
  function changeTest() {
    obj.a.b.c = 888
  }

  // 监视情况三: 监视 [reactive] 定义的 [对象类型] 数据, 且默认是开启深度监视的
  watch(person, (newValue, oldValue) => {
    console.log('person变化了', newValue, oldValue)
  })
  watch(obj, (newValue, oldValue) => {
    console.log('Obj变化了', newValue, oldValue)
  })
</script>

情况四

监视refreactive定义的对象类型数据中的某个属性

注意

  1. 若该属性值不是对象类型, 需要写成函数形式
  2. 若该属性值是对象类型, 可直接写, 也可写成函数, 推荐写成函数

结论: 监视的要是对象里的属性, 那么最好写函数式

若是对象监视的是地址值, 需要关注对象内部, 需要手动开启深度监视

vue
<template>
  <div class="person">
    <h1>情况四: 监视 [ref] 或 [reactive] 定义的 [对象类型] 数据中的某个属性</h1>
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <h2>汽车: {{ person.car.c1 }}、{{ person.car.c2 }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一台车</button>
    <button @click="changeC2">修改第二台车</button>
    <button @click="changeCar">修改整个车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { reactive, watch } from 'vue'

  // 数据
  let person = reactive({
    name: '张三',
    age: 18,
    car: {
      c1: '奔驰',
      c2: '宝马'
    }
  })

  // 方法
  function changeName() {
    person.name += '~'
  }
  function changeAge() {
    person.age += 1
  }
  function changeC1() {
    person.car.c1 = '奥迪'
  }
  function changeC2() {
    person.car.c2 = '大众'
  }
  function changeCar() {
    person.car = { c1: '雅迪', c2: '爱玛' }
  }

  // 监视情况四:
  // 监视响应式对象中的某个属性, 且该属性是基本类型的, 要写成函数式
  watch(()=> person.name, (newValue, oldValue) => {
    console.log('person.name变化了', newValue, oldValue)
  })

  // 监视响应式对象中的某个属性, 且该属性是对象类型的, 可以直接写, 也能写函数, 更推荐写函数
  watch(() => person.car, (newValue, oldValue) => {
    console.log('person.car变化了', newValue, oldValue)
  }, { deep: true })
</script>

情况五

监视上述的多个数据

vue
<template>
  <div class="person">
    <h1>情况五: 监视上述的多个数据</h1>
    <h2>姓名: {{ person.name }}</h2>
    <h2>年龄: {{ person.age }}</h2>
    <h2>汽车: {{ person.car.c1 }}、{{ person.car.c2 }}</h2>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一台车</button>
    <button @click="changeC2">修改第二台车</button>
    <button @click="changeCar">修改整个车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
  import { reactive, watch } from 'vue'

  // 数据
  let person = reactive({
    name: '张三',
    age: 18,
    car: {
      c1: '奔驰',
      c2: '宝马'
    }
  })
  // 方法
  function changeName() {
    person.name += '~'
  }
  function changeAge() {
    person.age += 1
  }
  function changeC1() {
    person.car.c1 = '奥迪'
  }
  function changeC2() {
    person.car.c2 = '大众'
  }
  function changeCar() {
    person.car = { c1: '雅迪', c2: '爱玛' }
  }

  // 监视, 情况五: 监视上述的多个数据
  watch([() => person.name, person.car ],(newValue, oldValue) => {
    console.log('person.car变化了', newValue, oldValue)
  }, { deep: true })
</script>