vue3中的watch详细讲解保证看的明明白白

Vue3 中的 watch 只能监视以下四种数据
1,ref 定义的数据。
2,一个响应式对象(如:reactive 定义的数据)。
3,函数的返回一个值(getter函数)。getter函数其实就是:能返回一个值的函数
4,由以上类型的值组成的数组
地址:https://cn.vuejs.org/api/reactivity-core.html#watch

vue3中watch监听 ref定义的基本数据类型
<template>
<div class="box">
姓 <input v-model="xingValue" /> <br>
<button @click="changeHandler">更改值</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
const xingValue = ref('Zhang');
function changeHandler(){
xingValue.value = 'Li';
}
watch(xingValue, (newValue,oldValue)=>{
console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
})
</script>

watch监听ref声明的数据,第1个参数是不需要点value
如果我们使用watch监听ref声明的数据,第1个参数是不需要点value的。
const age = ref(1);
// watch监听ref声明的数据,第1个参数是不需要点value
watch(age, (newValue,oldValue)=>{
console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
})
如果你使用ref声明的数据,如果你使用了点value。那么会报错的哈。

watch监听ref定义的对象数据类型
watch监听ref定义的【对象】数据类型时,监听的是对象的地址。
若是想要监听【对象内部属】性的变化,也就是细枝末节的变化。首要手动开启deep:true。
若是不开启deep:true,则监听不到。
watch监听ref定义的【对象】数据类型时,若是不开启deep:true,则监听不到对象内部属性的变化。
<template>
<div class="box">
<p>{{ perosn }}</p>
<button @click="changeHandler">更改值</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
const perosn = ref({
name: 'zhangsan',
age: 18
});
function changeHandler(){
perosn.value.age+=1
}
watch(perosn, (newValue,oldValue)=>{
console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
})
</script>
为啥更改ref定义的【对象】的属性时不会触发。
因为:watch监听ref定义的【对象】数据类型时,监听的是对象的地址。
地址没有发生改变,因此就不会触发。

如果想要:地址不发生改变时,也触发 ,需要开启:deep:true
watch开启deep:true监听ref对象内部属性的变化
watch开启deep:true监听ref对象内部属性的变化
<template>
<div class="box">
<p>{{ perosn }}</p>
<button @click="changeHandler">更改值</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
const perosn = ref({
name: 'zhangsan',
age: 18
});
function changeHandler(){
perosn.value.age+=1
}
watch(perosn, (newValue,oldValue)=>{
console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
},{
deep: true
})
</script>

watch监听ref定义的对象内部属性变化时,开启deep:true 新值和旧值是一样的

因为:watch监听ref定义的【对象】数据类型时,监听的是对象的地址。他们的地址是没有发生改变的。
watch监听ref定义的对象时,修改整个对象,newValue 和 oldValue 是不一样的
<template>
<div class="box">
<p>{{ perosn }}</p>
<button @click="allHandler">更改整个属性</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
const perosn = ref({
name: 'zhangsan',
age: 18
});
function allHandler(){
// 若修改整个ref 定义的对象,这个时候地址发生变化了。
// 如果你多次点击,会多次触发。
perosn.value = {
name: 'wangmazi',
age: 30
}
}
watch(perosn, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
},{
deep: true
})
</script>

总结:watch监听ref声明对象类型的数据时
watch监视 ref 定义的【对象类型】数据时,直接写数据名,监视的是对象的【地址值】
若想监视对象内部的数据,要手动开启深度监视
若修改的是 ref 定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
若修改整个ref 定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了

watch监视【reactive】定义的【对象类型数据】,默认是开启深度监视的
只要我们使用watch去监听reactive定义的对象类型数据
无论数据层级有多么深,watch都是可以监听到的,并且它默认是开启了深度监听的。
无论内部变化的是某个属性,还是对象,都可以监听到。
监听这种是最省心的,因为无论怎么变化,都是可以监听到的哈哈。
<template>
<div>
<h1>{{ person }}</h1>
<button @click="allHandler">更改car这个对象</button>
<button @click="oneNameHandler">更改某个属性name</button>
</div>
</template>
<script lang="ts" setup>
import { watch,reactive } from 'vue';
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allHandler(){
person.car = {
c1:'小米',
c2:'Su7'
}
}
function oneNameHandler(){
person.name = '李四';
}
// watch监视【reactive】定义的【对象类型数据】,默认是开启深度监视的
// 无论内部变化的是某个属性,还是对象,都可以监听到。
watch(person, (newValue,oldValue)=>{
console.log('新值:',newValue)
console.log('旧值:', oldValue)
})
</script>

有的文章会说:这种深度监听你是无法通过deep:false来进行关闭的。
这种说法不太正确,在现在的vue3.5版本中。
通过deep:false是可以关闭监听的。
<template>
<div class="box">
<p>{{ person }}</p>
<button @click="allHandler">更改整个属性</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, reactive } from 'vue';
const person = reactive({
a:{
b:{
c: 1
}
}
});
function allHandler(){
person.a.b.c +=1
}
watch(person, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
},{
deep: false,
})
</script>

watch监视 ref 或 reactive定义的【对象类型】数据中的某个属性
watch监视 ref 或 reactive定义的【对象类型】数据中的某个属性,注意点如下:
1,若该属性值是【对象类型】,可直接写数据源,也可写成函数(建议写成函数)。并且推荐开启深度监听。
2,若该属性值不是【对象类型】,需要写成函数形式。否则会在控制台产生告警。
若该属性值不是【对象类型】,需要写成函数形式
<template>
<div class="box">
<p>{{ person }}</p>
<button @click="allHandler">更改整个属性</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, reactive } from 'vue';
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allHandler(){
person.age+=1
}
// 监听person.age属性,会产生警告。
watch(person.age, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
})
</script>

const person = ref({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
watch(person.value.name, (newValue,oldValue)=>{
console.log('newValue', newValue)
console.log('oldValue', oldValue)
})

现在有警告。为啥会警告。
因为:watch监视 ref 或 reactive定义的【对象类型】数据中的某个属性时。
如果这个属性值不是对象类型时,需要写成函数形式。【重点】
// 因为这个属性值不是对象类型时,所以写成了函数形式
watch(()=> person.age, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
})

watch监听reactive定义的对象,监听的属性是对象(写成数据源形式),你替换整个对象,监听不到。
<template>
<div class="box">
<p>{{ person }}</p>
<button @click="allOneHandler">更改某个属性</button>
<button @click="allHandler">更改整个对象</button>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, reactive } from 'vue';
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allOneHandler(){
person.car.c1 = '--我的电动车--';
}
function allHandler(){
person.car = {
c1:'--电动车--',
c2:'--燃油车--'
}
}
watch(person.car, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
})
</script>

为什么上面的直接更改整个监听对象,监听不到。
person.car = {
c1:'--电动车--',
c2:'--燃油车--'
}
watch(person.car,()=>{})
因为:当你替换整个car的时候,已经不再是原来的car。因此无法监听到。
怎么让它也可以监听到呢?写成函数形式。
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allHandler(){
person.car = {
c1:'--电动车--',
c2:'--燃油车--'
}
}
watch(()=>person.car, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
})

写成函数形式,监听整某个具体属性又不行了。
<template>
<div>
<h1>{{ person }}</h1>
<button @click="allHandler">更改car这个对象</button>
<button @click="allOneHandler">更改某个属性</button>
</div>
</template>
<script lang="ts" setup>
import { watch,reactive } from 'vue';
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allHandler(){
person.car = {
c1:'--电动车--',
c2:'--燃油车--'
}
}
function allOneHandler(){
person.car.c1 += '--我的电动车--';
}
watch(()=>person.car, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
})
</script>

终极的解决办法
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allOneHandler(){
person.car.c1 += '--我的电动车--';
}
function allHandler(){
person.car = {
c1:'--电动车--',
c2:'--燃油车--'
}
}
watch(()=>person.car, (newValue,oldValue)=>{
console.log('新值:',newValue,'旧值:', oldValue)
},{ deep: true })

这样无论是更改整个对象还是对象内部的属性变化。都可以监听到啦。
总结:watch监听reactive/ref定义的内部属性时,监听的属性是对象,推荐写成函数形式,并且开启深度监听。
watch的数据源写成一个数组
有些时候,我们需要监听一个对象中的几个属性或者好几个不同的对象。
这个时候我们可以写成一个数组的形式
<template>
<div>
<h1>{{ person }}</h1>
<button @click="allHandler">更改car这个对象</button>
<button @click="oneNameHandler">更改某个属性name</button>
</div>
</template>
<script lang="ts" setup>
import { watch, reactive } from 'vue';
const person = reactive({
age:18,
name:'张三',
car:{
c1:'电动车',
c2:'燃油车'
}
});
function allHandler(){
person.car = {
c1:'小米Su7',
c2:'小米Yu7'
}
}
function oneNameHandler(){
person.name = '李四';
}
watch(()=>[person.name, person.car.c1], (newValue,oldValue)=>{
console.log('newValue', newValue)
console.log('oldValue', oldValue)
},{
deep:true
})
</script>

什么时候需要深度监听?
明明人家监听的是地址的变化,结果你想要监听某个值的变化
再次说明:watch为啥新值和旧值一样?
因为监听的是地址,你更改属性时,地址没有发生变化。
Object.assign更改时,也是只更改了属性,并没有产生新的地址。
相当于你新装修房子,你只换了灯,床,房子的地址没有发生变化。
因此:新值和旧值是一样的。
取消watch监听
将watch赋值给一个变量,调用这个变量。就可以停止监听了。
import { ref, computed, watch } from 'vue';
const age = ref(1);
function changeHandler(){
age.value +=1
}
let stopWatch = watch(age, (newValue,oldValue)=>{
console.log('watch监听到的值新值:',newValue,'旧值:', oldValue)
if(newValue>3){
stopWatch()
}
})
</script>

vue3中的watch详细讲解保证看的明明白白的更多相关文章
- vue中$nextTick详细讲解保证你一看就明白
1.功能描述 今天我们要实现这个一个小功能: 页面渲染完成后展示一个div元素: 当点击这个div元素后: div元素消失: 出现一个input元素:并且input元素聚焦 想必大家我觉得简单,我们一 ...
- Python中编码的详细讲解
看这篇文章前,你应该已经知道了为什么有编码,以及编码的种类情况 ASCII 占1个字节,只支持英文 GB2312 占2个字节,支持6700+汉字 GBK GB2312的升级版,支持21000+汉字 S ...
- flutter中ListView的详细讲解
1.ListView的简单介绍 ListView是最常用的可以滚动组件之一, 它可以沿一个方向进行线性排列所有的子组件. 下面是ListView的属性值介绍: scrollDirection:列表的滚 ...
- java中log4j用法详细讲解和一些小总结
0.Log4j的用法详解 首先,在项目中的classes 中新建立一个log4j.properties文件即可: 在实际编程时,要使Log4j真正在系统中运行事先还要对配置文件进行定义.定义步骤就是对 ...
- Unix操作系统中UUCP知识详细讲解
导读 Unix操作系统有很多值得学习的地方,这里我们主要介绍Unix操作系统中的uucp,大家一起来学习下吧!UUCP系统是一组程序,完成文件传输,执行系统之间的命令,维护系统使用情况的统计,保护安全 ...
- 关于ios中得路径详细讲解
利用create groups for any added folders 这样的方式表示的是将所有的资源都放在资源包得路径下,没有层次的概念利用create folder references fo ...
- 在Struts2中集成Spring详细讲解
Spring的官方定义是:一个轻量级的IoC和Aop容器框架,它使用了一种叫做依赖注入的技术. 所谓依赖注入,就是指将创建对象以及协议依赖对象之间合作的责任从对象自身中转移到"工厂" ...
- PHP中foreach用法详细讲解
1.foreach是什么? foreach是PHP的一种语法结构,其实就是一个工具,(工具:就是工作的时候用到的器具),那么在程序开发过程中,为了达到程序效果,就用到了foreach. 2.如何用? ...
- 第八节:详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架
前言 大家好,给大家带来详细讲解Java中的异常处理情况与I/O流的介绍以及类集合框架的概述,希望你们喜欢 JAVA 异常 try...catch...finally结构的使用方法 class Tes ...
- Hibernate中所有包作用详细讲解
http://liyanblog.cn/articles/2012/09/17/1347848802900.html Hibernate一共包括了23个jar包,令人眼花缭乱.本文将详细讲解Hiber ...
随机推荐
- 基于.NetCore开发 StarBlog 番外篇 (4) 文章一键发布工具Publisher大升级,AI功能增强与界面优化
前言 自从上次开发了 StarBlogPublisher 这个文章创作神器之后 我的博客+公众号文章工作流效率提升了不少 不过这软件还有一些功能欠缺和我不满意的地方 这次就在这个下暴雨的周末,把这个软 ...
- B1036 跟奥巴马一起编程
美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014年底,为庆祝"计算机科学教育周"正式启动,奥巴马编写了很简单的计算机代 ...
- sublime仿IDEA darcula主题
按ctrl+shif+p,输入install package,进入 搜索Darkula,出来的就是了,安装好后在配色方案里选择该主题即可. 记住,是Darkula ,不是darcula.
- 【公众号搬运】React-Native开发鸿蒙NEXT(6)
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- Java中XML相关
XML的两种解析方式: 1.DOM解析:将标记语言一次性读入内存并在内存中生成一颗DOM树(适用于服务端) 优点:操作方便,可以对文档进行CURD操作 缺点:由于它是一次性全部读入内存的所以占用内存空 ...
- `.NC`文件的读取与使用
.NC文件的读取与使用 前言 NetCDF(network Common Data Form)网络通用数据格式是一种面向数组型并适于网络共享的数据的描述和编码标准.目前,NetCDF广泛应用于大气科学 ...
- Springboot笔记<11>面向切面编程AOP
面向切面编程AOP AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中 ...
- PolarCTF网络安全2025春季个人挑战赛 web方向个人wp
xCsMsD 首先注册,注册后登录,显示一个xss窗口和一个cmd窗口,可以输入xss代码和命令执行指令 首先命令执行ls发现能够正确显示当前目录文件 然后尝试ls /发现没有回显,这时应该猜测是有过 ...
- String在内存中如何分布
一.设计思想及原理 设计思想 1.字符串分配和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能. 2.JVM为了提高性能和减少内存开销 ...
- [书籍精读]《JavaScript异步编程》精读笔记分享
写在前面 书籍介绍:本书讲述基本的异步处理技巧,包括PubSub.事件模式.Promises等,通过这些技巧,可以更好的应对大型Web应用程序的复杂性,交互快速响应的代码.理解了JavaScript的 ...