第十三节:带你梳理Vue2 : watch侦听器

ops/2024/10/18 14:26:03/
官方解释:> 观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代<br/>## 1.  侦听器的基本使用侦听器可以监听data对象属性或者计算属性的变化watch是观察属性的变化所以watch的属性名必须要与观察人的名字保持一致;只要观察的值发生了变化才会触发,```html
<div id="app"><!-- 监听器 --><input type="text" v-model="msg">
</div><script>   const vm = new Vue({el: "#app",data: {msg:""},watch:{msg(){console.log("数据发生了变化")console.log(arguments)}}})
</script>

通过这个理解,我们就会发现, 只要数据一但发生变化,那么监听函数msg就会被触发, 监听函数中接受两个参数,第一个参数是数据变化后的新值, 第二个参数是数据变化后的旧值


尽管大部分时间我们用不到侦听器, 但侦听器对于处理异步操作非常适合,

例如我们需要将用户输入的内容延迟5秒后现在在页面上

<div id="app"><!-- 监听器 --><input type="text" v-model="msg">{{showMsg}}
</div><script>javascript">   const vm = new Vue({el: "#app",data: {msg:"",showMsg: ""},watch:{msg(){let newValue = this.msgsetTimeout(() => {this.showMsg = newValue},5000)}}})
</script>

2. 获取旧值

侦听器在数据发生变化的时候就会触发,触发时,数据已经更新,我们那到就是新值,那么我们如何获取之前的旧值呢

其实当监听的属性发生变化时,侦听器会被传入两个参数

第一个参数:侦听器所监听属性的当前值,即更新后的值

第二个参数: 原来旧值

<div id="app"><!-- 监听器 --><input type="text" v-model="msg">
</div><script>javascript">   const vm = new Vue({el: "#app",data: {msg:"",},watch:{msg(val, oldval){console.log(val);console.log(oldval);            }}})
</script>

3. 监听data对象中某个对象的属性

data属性中的数据值除了是基本数据类型的数据外,还有可能是对象类型,那么我们如何监听对象数据的属性的

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price"></div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20},},watch:{fruit(val, oldval){console.log(val);console.log(oldval);            }}})
</script>

如果我们按照之前的监听方式, 那么我们就会发现,当我们修改fruit属性值的时候,侦听器不会被触发, 侦听器会在fruit对象整体被修改时触发.


为了监听对象里某个特定属性的变化,可以在侦听器的名称中使用.操作符, 就像访问这个对象的属性

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price"></div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20},},watch:{"fruit.price"(val, oldval){console.log(val);console.log(oldval);            }}})
</script>

4. 深度监听

通过上面的例子,我们知道,我们可以监听对象的特定属性的变化,可以我们想监听整个对象的所有属性的变化就需要给对象所有的属性添加监听就不是特别的好,如果我们只是单纯的监听对象,那么属性的变化并不会触发监听器,只有整个对象被替换时才会触发

所以我们可以通过deep属性来开启对象的深度监听,

4.1 deep 选项

为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。

如果需要开启深度监听,那么监听器将不再是一个函数,而需要写成一个对象,对象中配置deep属性

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price"></div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20},},watch:{fruit:{// 此时fruite 就是一个配置对象,里面的属性都是配置选项// handler 就是原来的监听函数, 当数据变化是执行的函数handler(val,oldval){console.log(val);console.log(oldval);            },// 深度监听选项deep:true}}})
</script>

此时我们就做到了即监听这整个对象的变化, 也简体对象里面所有的属性的变化,


4.2 immediate选项

监听除了deep选项外,还有immediate选项

指定 immediate: true 将立即以表达式的当前值触发回调,

watch:{fruit:{// 此时fruite 就是一个配置对象,里面的属性都是配置选项// handler 就是原来的监听函数, 当数据变化是执行的函数handler(val,oldval){console.log(val);console.log(oldval);            },// 深度监听选项deep:true,immediate: true  // 理解执行监听函数handler}
}

5. 引用类型深度监听后,属性变化,获取新旧值问题

但是细心的朋友就会发现我们在改变对象属性的时候,虽然触发了侦听器,但是我没发获取旧值了,我们拿到的两个形参的值都是对象更改后的新值.

出于某种原因没有深入过滤对象的每个属性,那么只能监听到对象的变化,而JavaScript里对象的赋值是引用赋值,虽然属性变化了,但是它引用的地址却一直没有变化,这样的话,当对象的属性值改变了,Vue虽然知道它改变了,但也只能循着引用地址去获得对象,可此时对象的属性的值已经改变了,因此Vue并不能得到变异之前的值。

示例:

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price"></div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20},},watch:{fruit:{handler(val,oldval){console.log(11)console.log(val);console.log(oldval);            },deep:true}},})
</script>

此时当数据发生变化是, 查看handler 两个参数值

监听属性.png


5.1 解决方案: 利用计算属性

官方方案: 观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代


既然 watch无法在变异对象或数组时监听新旧值,那么我们可以先使用JSON.parse()来浅复制一遍data对象,然后在复制的对象上修改,完了重新赋值给该data对象,这样变化前后两个对象是完全不一样的,因为它们的引用地址完全不一样,Vue可以循着两个引用地址获得新旧两个

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price"></div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20},},watch:{fruitNew:{handler(val,oldval){console.log(11)console.log(val);console.log(oldval);            },deep:true}},computed:{fruitNew(){return JSON.parse(JSON.stringify(this.fruit));}},})
</script>

6. 可以通过Vue是实例对象的$watch属性来监听

除了 watch 选项之外,您还可以使用命令式的 vm.$watch ,通过Vue实例对象来监听数据


6.1 普通监听

可以通过实例对象调用$watch设置监听

<!-- 监听字符变化-->
<div id="app"><!-- 监听器 --><input type="text" v-model="msg"></div><script>javascript">   const vm = new Vue({el: "#app",data: {msg:'你好'}})// $watch 是一个实例方法vm.$watch("msg",(val,newVal) => {console.log(val)console.log(newVal);       })
</script>

6.2 监听配置

<div id="app"><!-- 监听器 --><input type="text" v-model.number="fruit.price">
</div><script>javascript">   const vm = new Vue({el: "#app",data: {fruit:{name:"苹果",price: 20`在这里插入代码片`},}})// $watch 是一个实例方法vm.$watch("fruit",(val,newVal) => {console.log(val)console.log(newVal);       },{deep: true})
</script>

http://www.ppmy.cn/ops/45038.html

相关文章

电脑同时配置两个版本mysql数据库常见问题

1.配置时&#xff0c;要把bin中的mysql.exe和mysqld.exe 改个名字&#xff0c;不然两个版本会重复&#xff0c;当然&#xff0c;在初始化数据库的时候&#xff0c;如果时57版本的&#xff0c;就用mysql57(已经改名的)和mysqld57 代替 mysql 和 mysqld 例如 mysql -u root -p …

Unix环境高级编程--8-进程控制---8.1-8.2进程标识-8.3fork函数-8.4 vfork函数

1、进程控制几个过程 创建进程--》执行进程---》终止进程 2、进程标识 &#xff08;1&#xff09;专用进程&#xff1a;ID为0的进程是调度进程&#xff0c;常常被称为交换进程&#xff0c;也称为系统进程&#xff1b; ID为1通常是init进程&#xff0c;在自举结束时由内核调用…

轧钢测径仪分析软件,四大图表带来产线新视角!

轧钢测径仪是智能化检测设备&#xff0c;除了测径仪主体外&#xff0c;还配有测控软件系统&#xff0c;从这里可对测径仪进行各种设置&#xff0c;亦可从此观测到测径仪获得的各种信息&#xff0c;如检测信息、分析图表、计算尺寸、历史数据等。而从测径仪获得的图表信息主要有…

leetcode-顺时针旋转矩阵-111

题目要求 思路 1.假设现在有一个矩阵 123 456 789 2.我们可以根据19这个对角线将数据进行交换&#xff0c;得到矩阵 147 258 369 3.然后将矩阵每一行的数据再翻转&#xff0c;得到矩阵 741 852 963 代码实现 class Solution { public:vector<vector<int> > rot…

Web基础与HTTP协议

域名概念 1、网络是基于 TCP/IP 协议进行通讯和连接的&#xff0c;每一台主机都有一个唯一的标识&#xff08;固定的IP地址&#xff09;&#xff0c;用以区别在网络上成千上万个用户和计算机。网络在区分所有与之相连的主机和网络时&#xff0c;均采用一种唯一、通用的地址格式…

YOLO-10更快、更强

YOLO-10简介 主要贡献&#xff1a; 无NMS的一致双分配 YOLOv10提出了一种通过双标签分配而不用非极大值抑制NMS的策略。这种方法结合了一对多和一对一分配策略的优势&#xff0c;提高了效率并保持了性能。 高效的网络设计 轻量化分类头&#xff1a;在不显著影响性能的情况下&a…

《微服务王国的守护者:Spring Cloud Dubbo的奇幻冒险》

5. 经典问题与解决方案 5.3 服务追踪与链路监控 在微服务架构的广袤宇宙中&#xff0c;服务间的调用关系错综复杂&#xff0c;如同一张庞大的星系网络。当一个请求穿越这个星系&#xff0c;经过多个服务节点时&#xff0c;如何追踪它的路径&#xff0c;如何监控整个链路的健康…

【MySQL精通之路】SQL优化(1)-查询优化(10)-外部联接简化

主博客&#xff1a; 【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客 上一篇&#xff1a; 【MySQL精通之路】SQL优化(1)-查询优化(9)-外部联接优化-CSDN博客 下一篇&#xff1a; 【MySQL精通之路】SQL优化(1)-查询优化(11)-多范围查询优化-CSDN博客 查询时FROM子句中的表达…