【Vue3】watch监听的五种情况

学习来源:尚硅谷

  • 作用:监视数据的变化(和Vue2中的watch作用一致)
  • 特点:Vue3中的watch只能监视以下四种数据
  1. ref定义的数据。
  2. reactive定义的数据。
  3. 函数返回一个值(getter函数)。
  4. 一个包含上述内容的数组。

在vue3中,如果我们要定义响应式数据,可以采用ref和reactive声明定义变量,我们在Vue3中使用watch的时候,通常会遇到以下几种情况:

1、※※※ 监听ref定义的基本类型数据

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

<script setup>
/**
 * 监视`ref`定义的【基本类型】数据:直接写数据名即可,监视的是其`value`值的改变。
 */
import { ref, watch } from 'vue'

let num = ref(1)

function updateNum() {
  num.value++
}

watch(num, (vul) => {
  console.log('num变化了:', vul)
})
</script>

<template>
  <h1>
    {{ num }}
  </h1>
  <button @click="updateNum">num+1</button>
</template>

2、监听ref定义的对象类型数据

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

注意:

  • 若修改的是ref定义的对象中的属性,newValueoldValue 都是新值,因为它们是同一个对象。

  • 若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。

<script setup>
/**
 * 监视`ref`定义的【对象类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视。
 */
import { ref, watch } from 'vue'

let person = ref({
  name: 'zs',
  age: 13
})

function updateName(){
  person.value.name += '~'
}

function updatePerson() {
  person.value = {
    name: 'ls',
    age: 18
  }
}

watch(person, (vul) => {
  console.log('person变化了', vul)
}, {
  deep: true
})
</script>

<template>
  <h1>姓名: {{ person.name }}</h1>
  <h1>年龄: {{ person.age }}</h1>
  <button @click="updateName">修改姓名</button>
  <button @click="updatePerson">修改整个人</button>
</template>

3、监听reactive定义的对象类型数据

当然了,reactive也不能定义基本类型数据,

监视reactive定义的【对象类型】数据,且默认开启了深度监视,并且是不可关闭的深度监听。数据中的任何一点蛛丝马迹的变化,都会被监听到。

<script setup>
// 监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。
import { reactive, watch } from 'vue'

let person = reactive({
  name: 'zs',
  age: 18,
  car: {
    c1: 'c1',
    c2: 'c2'
  }
})

function updateName() {
  person.name += '~'
}

function updatePerson() {
  person = Object.assign(person, {
    name: 'lisi',
    age: 13
  })
}

function updateCar() {
  person.car.c1 += '1'
}

watch(person, (vul) => {
  console.log('person变化了', vul)
})
</script>

<template>
  <h1>姓名: {{ person.name }}</h1>
  <h1>年龄: {{ person.age }}</h1>
  <h1>car: {{ person.car.c1 + '--' + person.car.c2 }}</h1>
  <button @click="updateName">修改姓名</button>
  <button @click="updatePerson">修改整个人</button>
  <button @click="updateCar">修改car</button>
</template>

4、※※※ 监听ref或reactive定义的数据中的某个属性 ※

监视refreactive定义的【对象类型】数据中的某个属性,注意点如下:

  1. 若该属性值不是【对象类型】,需要写成函数形式。
  2. 若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。

结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。

<script setup>
// 监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。
import { reactive, watch } from 'vue'

let person = reactive({
  name: 'zs',
  age: 18,
  car: {
    c1: 'c1',
    c2: 'c2'
  }
})

function updateName() {
  person.name += '~'
}

function updatePerson() {
  person = Object.assign(person, {
    name: 'lisi',
    age: 13
  })
}

function updateCar() {
  person.car.c1 += '1'
}

watch(() => person.name, (vul) => {
  console.log('person.name变化了', vul)
})

watch(() => person.car, (vul) => {
  console.log('person.car变化了', vul)
}, {
  deep: true
})

</script>

<template>
  <h1>姓名: {{ person.name }}</h1>
  <h1>年龄: {{ person.age }}</h1>
  <h1>car: {{ person.car.c1 + '--' + person.car.c2 }}</h1>
  <button @click="updateName">修改姓名</button>
  <button @click="updatePerson">修改整个人</button>
  <button @click="updateCar">修改car</button>
</template>

5、组合监听多个数据

组合监听多个数据,使用数组进行包裹

<template>
  <h1>sum: {{ sum }}</h1>
  <h1>name: {{ person.name }}</h1>
  <button @click="updateSum">修改sum</button>
  <button @click="updateName">修改name</button>
</template>

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

let sum = ref(0)
let person = reactive({
  name: 'zs'
})

function updateName() {
  person.name += '~'
}

function updateSum() {
  sum.value += 1
}

watch([sum, person], (newVal) => {
  console.log('数据变化了:', newVal)
})
</script>

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐