您的位置:首页 > 游戏 > 游戏 > 【Vue3】watch 监视对象类型数据中的某个属性

【Vue3】watch 监视对象类型数据中的某个属性

2025/4/18 10:04:50 来源:https://blog.csdn.net/Silent_Paladin/article/details/140674098  浏览:    关键词:【Vue3】watch 监视对象类型数据中的某个属性

【Vue3】watch 监视对象类型数据中的某个属性

  • 背景
  • 简介
  • 开发环境
  • 开发步骤及源码
    • 监视对象中值为基本类型的属性
    • 监视对象中值为对象类型的属性

背景

随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创,大多是参考其他文章资料整理所得,感谢每位技术人的开源精神。

简介

本文介绍 Vue3 中如何使用 watch 函数监视 refreactive 定义的对象类型数据中的某个属性。

开发环境

分类名称版本
操作系统WindowsWindows 11
IDEVisual Studio Code1.91.1

开发步骤及源码

在 【Vue3】watch 监视 reactive 定义的数据 基础上修改 Vue 根组件 App.vue 代码。

监视对象中值为基本类型的属性

<template><div class="person"><h1>监视对象中值为基本类型的属性</h1><h2>姓名:{{ person.name }}</h2><h2>年龄:{{ person.age }}</h2><button @click="growUp">长大</button></div>
</template><script setup lang="ts" name="App">
import { reactive, watch } from 'vue'const person = reactive({name: 'Harry Potter',age: 10,
})function growUp() {person.age += 1
}const stopWatchAge = watch(() => person.age, (newValue, oldValue) => {console.log('%s 又长大一岁,从 %d 岁到 %d 岁', person.name, oldValue, newValue)if (newValue >= 18) {console.log('%s 成人了,可以不用再监护了', person.name)stopWatchAge()}
})
</script><style scoped>
button {margin-right: 10px;
}
</style>

若监视的对象属性值是基本类型,则第一个参数需要写成 getter 函数形式(本例中使用箭头函数 () => person.age),不能直接写 对象.属性,否则会报错。点击 长大 按钮后日志输出如下:
监视对象中值为基本类型的属性

监视对象中值为对象类型的属性

<template><div class="person"><h1>监视对象中值为对象类型的属性</h1><h2>姓名:{{ person.name }}</h2><h2>电影:{{ person.film.f1 }} | {{ person.film.f2 }}</h2><button @click="changeFilm">修改全部电影</button><button @click="changeFilm1">修改第一部电影</button><button @click="changeFilm2">修改第二部电影</button></div>
</template><script setup lang="ts" name="App">
import { reactive, watch } from 'vue'const person = reactive({name: 'Harry Potter',film: {f1: '哈利·波特与魔法石',f2: '哈利·波特与密室',}
})function changeFilm() {person.film = {f1: '哈利·波特与阿兹卡班的囚徒',f2: '哈利·波特与火焰杯',}
}function changeFilm1() {person.film.f1 = '哈利·波特与凤凰社'
}function changeFilm2() {person.film.f2 = '哈利·波特与混血王子'
}watch(person.film, (newValue, oldValue) => {console.log(person.name, '出演电影', oldValue, newValue)
})
</script><style scoped>
button {margin-right: 10px;
}
</style>

与监视对象中值为基本类型的属性不同之处在于,watch 的第一个参数可以写成 对象.属性,并不会报错,但是此时点击 修改第一部电影修改第二部电影 按钮都有日志输出,但是点击 修改全部电影 按钮没有任何日志输出。因为监视的原对象 film: { f1: '哈利·波特与魔法石', f2: '哈利·波特与密室', } 已经被整体替换成了 { f1: '哈利·波特与阿兹卡班的囚徒', f2: '哈利·波特与火焰杯', }。如果想保持整体对象监听,则 watch 的第一个参数需要写成 getter 函数形式。

<template><div class="person"><h1>监视对象中值为对象类型的属性</h1><h2>姓名:{{ person.name }}</h2><h2>电影:{{ person.film.f1 }} | {{ person.film.f2 }}</h2><button @click="changeFilm">修改全部电影</button><button @click="changeFilm1">修改第一部电影</button><button @click="changeFilm2">修改第二部电影</button></div>
</template><script setup lang="ts" name="App">
import { reactive, watch } from 'vue'const person = reactive({name: 'Harry Potter',film: {f1: '哈利·波特与魔法石',f2: '哈利·波特与密室',}
})function changeFilm() {person.film = {f1: '哈利·波特与阿兹卡班的囚徒',f2: '哈利·波特与火焰杯',}
}function changeFilm1() {person.film.f1 = '哈利·波特与凤凰社'
}function changeFilm2() {person.film.f2 = '哈利·波特与混血王子'
}watch(() => person.film, (newValue, oldValue) => {console.log(person.name, '出演电影', oldValue, newValue)
})
</script><style scoped>
button {margin-right: 10px;
}
</style>

此时点击 修改全部电影 按钮有日志输出,但是点击 修改第一部电影修改第二部电影 按钮不再有日志输出。如果想要监视整体对象,同时还要监视对象中的属性,则还需手动开启深度监视。

<template><div class="person"><h1>监视对象中值为对象类型的属性</h1><h2>姓名:{{ person.name }}</h2><h2>电影:{{ person.film.f1 }} | {{ person.film.f2 }}</h2><button @click="changeFilm">修改全部电影</button><button @click="changeFilm1">修改第一部电影</button><button @click="changeFilm2">修改第二部电影</button></div>
</template><script setup lang="ts" name="App">
import { reactive, watch } from 'vue'const person = reactive({name: 'Harry Potter',film: {f1: '哈利·波特与魔法石',f2: '哈利·波特与密室',}
})function changeFilm() {person.film = {f1: '哈利·波特与阿兹卡班的囚徒',f2: '哈利·波特与火焰杯',}
}function changeFilm1() {person.film.f1 = '哈利·波特与凤凰社'
}function changeFilm2() {person.film.f2 = '哈利·波特与混血王子'
}watch(() => person.film, (newValue, oldValue) => {console.log(person.name, '出演电影', oldValue, newValue)
}, {deep: true
})
</script><style scoped>
button {margin-right: 10px;
}
</style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com