watch

小提示

作用:侦听数据的变化(和Vue2中的watch作用一致)

特点:watch() 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。

语法:watch(sources, callback, options)

参数 参数描述
1 sources 侦听器的 一个 ref
一个响应式对象
一个函数,返回一个值
由以上类型的值组成的数组
2 callback 在发生变化时要调用的回调函数 这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。
3 options 一个对象(可选的参数) immediate :在侦听器创建时立即触发回调。第一次调用时旧值是 undefined
deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。
flush:调整回调函数的刷新时机。
onTrack / onTrigger:调试侦听器的依赖。
once:只运行一次回调,在第一次回调运行后,侦听程序自动停止。

1 侦听ref定义的数据

基本类型

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

1<template>
2  <div>
3    {{ num }}
4    <button @click="add">增加</button>
5  </div>
6</template>
7
8<script lang="ts" setup>
9import {ref, watch} from 'vue'
10
11let num = ref(0)
12
13let stopWatch = watch(num, (value, oldValue) => {
14  console.log(value, oldValue)
15  // 当value等于10时停止侦听
16  if (value === 10) {
17    stopWatch()
18  }
19})
20
21function add() {
22  num.value += 1
23}
24</script>

对象类型

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

注意

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

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

1<template>
2  <div>
3    <p>{{ person.name }}</p>
4    <p>{{ person.age }}</p>
5    <button @click="changeName">修改名字</button>
6    <button @click="changeAge">修改年龄</button>
7    <button @click="changePerson">修改</button>
8  </div>
9</template>
10
11<script lang="ts" setup>
12import {ref, watch} from 'vue'
13
14let person = ref({
15  name: '钢铁侠',
16  age: 30
17})
18
19watch(person, (value, oldValue) => {
20  console.log(value, oldValue)
21}, {deep: true, immediate: true})
22
23function changeName() {
24  person.value.name += '~'
25}
26
27function changeAge() {
28  person.value.age += 1
29}
30
31function changePerson() {
32  person.value = {
33    name: '美国队长',
34    age: 30
35  }
36}
37</script>

2 侦听一个响应式对象

侦听 reactive 定义的【对象类型】数据,默认开启了深度侦听,并且该深度侦听无法关闭。

注意:newValue和oldValue都是新值,因为它们是同一个对象

1<template>
2  <div>
3    <p>{{ person.name }}</p>
4    <p>{{ person.age }}</p>
5    <button @click="changeName">修改名字</button>
6    <button @click="changeAge">修改年龄</button>
7    <button @click="changePerson">修改</button>
8  </div>
9</template>
10
11<script lang="ts" setup>
12import {reactive, watch} from 'vue'
13
14let person = reactive({
15  name: '钢铁侠',
16  age: 30
17})
18
19watch(person, (value, oldValue) => {
20  console.log(value, oldValue)
21})
22
23function changeName() {
24  person.name += '~'
25}
26
27function changeAge() {
28  person.age += 1
29}
30
31function changePerson() {
32  Object.assign(person, {
33    name: '美国队长',
34    age: 30
35  })
36}
37</script>

3 一个函数,返回一个值

侦听 ref 或 reactive 定义的【对象类型】数据中的某个属性

  1. 若该属性值是基本类型,需要写成函数形式

  2. 若该属性值是对象类型,可直接写,也可写成函数形式,建议写成函数形式

    • 侦听的是地址值,如需侦听对象内部,需要手动开启深度侦听
1<template>
2  <div>
3    <p>{{ person.name.familyName }}</p>
4    <p>{{ person.age }}</p>
5    <button @click="changeName">修改名字</button>
6    <button @click="changeAge">修改年龄</button>
7    <button @click="changePerson">修改</button>
8  </div>
9</template>
10
11<script lang="ts" setup>
12import {reactive, watch} from 'vue'
13
14let person = reactive({
15  name: {
16    familyName: 'Stark',
17    firstName: 'Tony'
18  },
19  age: 30
20})
21// 侦听响应式对象中的某个属性,且该属性是基本类型,要写成函数式
22watch(() => person.age, (value, oldValue) => {
23  console.log(value, oldValue)
24})
25// 侦听响应式对象中的某个属性,且该属性是对象类型,可以直接写,也可以写成函数式,更推荐写成函数
26
27watch(person.name, (value, oldValue) => {
28  console.log('只侦听属性值,更改地址值后不再继续侦听', value, oldValue)
29})
30
31watch(() => person.name, (value, oldValue) => {
32  console.log('只侦听地址值', value, oldValue)
33})
34  
35watch(() => person.name, (value, oldValue) => {
36  console.log('同时侦听属性值和地址值', value, oldValue)
37}, {deep: true})
38
39
40function changeName() {
41  person.name.familyName += '~'
42}
43
44function changeAge() {
45  person.age += 1
46}
47
48function changePerson() {
49  Object.assign(person, {
50    name: {
51      familyName: 'Rogers',
52      firstName: 'Steve'
53    },
54    age: 30
55  })
56}
57</script>

4 由以上类型的值组成的数组

1<template>
2  <div>
3    <p>{{ person.name.familyName }}</p>
4    <p>{{ person.age }}</p>
5    <button @click="changeName">修改名字</button>
6    <button @click="changeAge">修改年龄</button>
7    <button @click="changePerson">修改</button>
8  </div>
9</template>
10
11<script lang="ts" setup>
12import {reactive, watch} from 'vue'
13
14let person = reactive({
15  name: {
16    familyName: 'Stark',
17    firstName: 'Tony'
18  },
19  age: 30
20})
21
22watch([person, () => person.name], (value, oldValue) => {
23  console.log(value, oldValue)
24})
25
26
27function changeName() {
28  person.name.familyName += '~'
29}
30
31function changeAge() {
32  person.age += 1
33}
34
35function changePerson() {
36  Object.assign(person, {
37    name: {
38      familyName: 'Rogers',
39      firstName: 'Steve'
40    },
41    age: 30
42  })
43}
44</script>