【vue3】wacth监听,监听ref定义的数据,监听reactive定义的数据,详解踩坑点

news2024/11/23 12:59:45

假期第二篇,对于基础的知识点,我感觉自己还是很薄弱的。
趁着假期,再去复习一遍

之前已经记录了一篇【vue3基础知识点-computed和watch】
今天在学习的过程中发现,之前记录的这一篇果然是很基础的,很多东西都讲的不够细致

话不多说,进入正题:

vue2

vue2中的watch写法,(vue3可以向下兼容vue2的写法)

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <button @click="sum++">点我+1</button>
  </div>
</template>

<script >

import { ref, watch } from 'vue';
export default {
name:'demo',
watch: {
  // vue2简单写法
  sum(newVal, oldVal) {
    console.log('sum的值变化了', newVal, oldVal);
  }
  //vue2完整写法
  sum:{
    handler(newVal,oldval){
    console.log('sum的值变化了', newVal, oldVal);
    },
    deep:true,
    immediate:true
  }
},
setup(){
  let sum = ref(0)
  return {
    sum
  }
}
}

</script>

在这里插入图片描述
虽然vue3中可以使用vue2的写法,但是混合使用会导致代码风格不一致,增加维护成本。而且我们只是习惯了vue2的写法,全都使用vue3的写法,其实就是一个熟悉的过程,vue3 的 < script setup> 语法和 Composition API组合式api还是很香的,慢慢来吧

组合式api其实就是一堆内置的函数,需要用什么就引入对应的函数,如ref、wacth等

vue3

1、监听ref定义的单个响应式数据

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <button @click="sum++">点我+1</button>
  </div>
</template>
<script >
import { ref, watch } from 'vue';
export default {
name:'demo',
setup(){
  let sum = ref(0)
  //第一个参数,要监听的数据
  //第二个参数,回调函数,两种写法:箭头函数或者普通函数都可以
  //(在vue3中,wathc的回调函数可以写成箭头函数,因为setup中this是undefined,没有响应式的this上下文)

  //箭头函数写法
  watch(sum,(newVal,oldval)=>{
    console.log('sum变了',newVal,oldval)
    unde
  })
  // 普通函数写法
    watch(sum,function(newVal,oldval){
    console.log('sum变了',newVal,oldval)
  })
  return {
    sum
  }
}

}

2、监听ref定义的多个响应式数据

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <button @click="sum++">点我+1</button>
    <h2>当前招呼语:{{msg}}</h2>
    <button @click="msg+='wow'">点我打招呼</button>
  </div>
</template>
<script >
import { ref, watch } from 'vue';
export default {
name:'demo',
setup(){
  let sum = ref(0)
  let msg = ref('hello')
//vue2中watch是配置项,只能写一个;vue3中watch是函数,可以调用n次
watch(sum,(newVal,oldVal)=>{
  console.log('sum变了',newVal,oldVal);
})
watch(msg,(newVal,oldVal)=>{
  console.log('msg',newVal,oldVal);
})
  return {
    sum,
    msg
  }
}
}
</script>

这种写法虽然可以多次调用watch函数,但是还有更简化的写法

<template>
  <div>
    <h1>当前求和为:{{ sum }}</h1>
    <button @click="sum++">点我+1</button>
    <h2>当前招呼语:{{ msg }}</h2>
    <button @click="msg += 'wow'">点我打招呼</button>
  </div>
</template>
<script >
import { ref, watch } from "vue";
export default {
  name: "demo",
  setup() {
    let sum = ref(0);
    let msg = ref("hello");
//第一个参数为数组,第二个参数为回调函数
    watch([sum, msg], (newVal, oldVal) => {
      console.log("sum或msg变了", newVal, oldVal);
    });
    return {
      sum,
      msg,
    };
  },
};
</script>

在这里插入图片描述
在这里插入图片描述
vue3 watch中的参数,第三个就是配置项

注意点:监听ref定义的数据不需要写deep:true,简单数据类型不需要深度监听,ref定义的对象,本质上还是调用了reactive将其包装成响应式对象,所以ref定义的对象默认开启了深度监听

watch(source: WatchSource, cb: WatchCallback, options?: WatchOptions): StopHandle
source: 监听的源(可以是响应式数据、计算属性或ref等)
cb: 当源发生变化时被调用的回调函数
options(可选): 一个对象,包含额外的选项配置
返回一个停止监听的函数

    let sum = ref(0);
    let msg = ref("hello");
    //监听单个
     watch(sum, (newVal, oldVal) => {
      console.log("sum变了", newVal, oldVal);
    },{
      immediate:true
    });
   //监听多个

    watch([sum, msg], (newVal, oldVal) => {
      console.log("sum或msg变了", newVal, oldVal);
    },{
      immediate:true
    });

3、监听reactive定义的单个响应式数据的全部属性

<template>
  <div>
<h2>姓名:{{person.name}}</h2>
<h2>性别:{{person.sex}}</h2>
<button @click="person.name+='~'">姓名变了</button>

<button  @click="person.sex+='!'">性别变了</button>
  </div>
</template>
<script >
import {reactive,watch } from "vue";
export default {
  name: "demo",
  setup() {
   
    let person = reactive({
      name:'莲花',
      sex:'男'
      
    })
        watch(person, (newVal, oldVal) => {
      console.log("person变了", newVal, oldVal);
    });

    return {
      person
    };
  },
};
</script>

这有个踩坑点,recative定义的响应式数据,交给watch进行监听,此处无法正确的获得oldValue,watch默认只能追踪到响应式数据属性的变化,但并不会记录变化前的旧值
在这里插入图片描述
如果reactive定义的数据嵌套很深,在vue2中需要开启深度监听才能监听到,但是vue3中却不需要

<template>
  <div>
<h2>姓名:{{person.name}}</h2>
<h2>性别:{{person.sex}}</h2>
<h2>工作:{{person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import { ref, reactive,watch } from "vue";
export default {
  name: "demo",
  setup() {
    let person = reactive({
      name:'莲花',
      sex:'男',
      job:{
        job1:{
          work:'侦探'
        }
      }      
    })
        watch(person, (newVal, oldVal) => {
      console.log("person变了", newVal, oldVal);
    });
    return {
  
      person
    };
  },
};
</script>

reactive定义的数据强制开启了深度监听,即使写deep:false,配置也无效,无法手动关闭深度监听
在这里插入图片描述
4、监听reactive定义的单个响应式数据中的某一个属性

如果这样写,是没有效果的

<template>
  <div>
<h2>姓名:{{person.name}}</h2>
<h2>性别:{{person.sex}}</h2>
<h2>工作:{{person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import { ref, reactive,watch } from "vue";
export default {
  name: "demo",
  setup() {   
    let person = reactive({
      name:'莲花',
      sex:'男',
      job:{
        job1:{
          work:'侦探'
        }
      }      
    })
        watch(person.name, (newVal, oldVal) => {
      console.log("person.name变了", newVal, oldVal);
    });
    return {  
      person
    };
  },
};
</script>

控制台中会提示:这样不能监听,只能监听ref定义的值,或reactive生成的响应式对象,或者是一个数组,而person.name只是reactive生成的响应式对象中的一个属性

在这里插入图片描述
那么监听reactive生成的响应式对象中的一个属性,写法应该是这样的:

先写一个函数,函数有返回值,想监听谁就返回谁

<template>
  <div>
<h2>姓名:{{person.name}}</h2>
<h2>性别:{{person.sex}}</h2>
<h2>工作:{{person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import { ref, reactive,watch } from "vue";
export default {
  name: "demo",
  setup() {
    let person = reactive({
      name:'莲花',
      sex:'男',
      job:{
        job1:{
          work:'侦探'
        }
      }      
    })
    watch(
   () => person.name,
  (newValue, oldValue) => {
    console.log(`person变了 发生了变化: ${oldValue} -> ${newValue}`);
  }
    )
    return {  
      person
    };
  },
};
</script>

在这里插入图片描述
5、监听reactive定义的单个响应式数据中的某一些属性

<template>
  <div>
<h2>姓名:{{person.name}}</h2>
<h2>性别:{{person.sex}}</h2>
<h2>工作:{{person.job.job1.work}}</h2>
<button @click="person.name+='~'">姓名变了</button>
<br/>
<br/>
<br/>
<button  @click="person.sex+='!'">性别变了</button>
<br/>
<br/>
<br/>
<button  @click="person.job.job1.work+='还有其他工作'">工作变了</button>
  </div>
</template>
<script >
import { ref, reactive,watch } from "vue";
export default {
  name: "demo",
  setup() {
   
    let person = reactive({
      name:'莲花',
      sex:'男',
      job:{
        job1:{
          work:'侦探'
        }
      }
      
    })
    watch(
    //第一个参数改为数组
    //newValue, oldValue也会变成数组格式
         [ () => person.name,() => person.sex],
         (newValue, oldValue) => {
         console.log(`person的name或sex变了 `,newValue, oldValue);
       }
    )  
    return {  
      person
    };
  },
};
</script>

在这里插入图片描述

6、特殊情况,监听job,job是person中的对象,直接这样写是监听不到的,原因是改的内容层次比较深,我们要改的是job中job1中的work

   let person = reactive({
      name:'莲花',
      sex:'男',
      job:{
        job1:{
          work:'侦探'
        }
      }
      
    })
    watch(
          () => person.job,
         (newValue, oldValue) => {
         console.log(`person的job变了 `,newValue, oldValue);
       }
    )  

这个时候就需要配置项中配置deep了

      watch(
          () => person.job,
         (newValue, oldValue) => {
         console.log(`person的job变了 `,newValue, oldValue);
       },{deep:true}
    )  

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054378.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gcc中-I(大写的i)参数的作用

《gcc -I -L -l区别》是我参考的一篇博客。 gcc中-I参数可以帮助找到头文件的目录&#xff0c;比如在当前目录下有一个名为includeTestCom.c的c文件和名为includeCom的目录。 includeTestCom.c里边的内容如下&#xff1a; #include "good.h" int main(){printf(&q…

自己动手写编译器:实现命令行模块

在前面一系列章节中&#xff0c;我们完成了词法解析的各种算法。包括解析正则表达式字符串&#xff0c;构建 NFA 状态就&#xff0c;从 NFA 转换为 DFA 状态机&#xff0c;最后实现状态机最小化&#xff0c;接下来我们注重词法解析模块的工程化实现&#xff0c;也就是我们将所有…

CCF-CSP真题《202309-1 坐标变换(其一)》思路+python,c++,java满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202309-1试题名称&#xff1a;坐标变换&#xff08;其一&#xff09;时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 对于平面直角坐标…

11链表-迭代与递归

目录 LeetCode之路——206. 反转链表 分析&#xff1a; 解法一&#xff1a;迭代 解法二&#xff1a;递归 LeetCode之路——206. 反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head […

git你学“废”了吗?——git撤销操作指令详解

git你学“废”了吗&#xff1f;——git撤销操作指令详解&#x1f60e; 前言&#x1f64c;撤销的本质撤销修改情况一&#xff1a;撤销工作区的修改方式一&#xff1a;方式二&#xff1a;演示截图&#xff1a; 撤销修改情况二&#xff1a;撤销暂存区和工作区的修改操作截图&#…

【Java 进阶篇】JDBC DriverManager 详解

JDBC&#xff08;Java Database Connectivity&#xff09;是 Java 标准库中用于与数据库进行交互的 API。它允许 Java 应用程序连接到各种不同的数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;执行 SQL 查询和更新操作&#xff0c;以及处理数据库事务。在 JDBC 中&am…

链表经典面试题(一)

面试题 1.反转链表的题目2.反转链表的图文分析3.反转链表的代码实现 1.反转链表的题目 2.反转链表的图文分析 我们在实现反转链表的时候,是将后面的元素变前面&#xff0c;前面的元素变后面&#xff0c;那么我们是否可以理解为&#xff0c;用头插法的思想来完成反转链表呢&…

力扣:116. 填充每个节点的下一个右侧节点指针(Python3)

题目&#xff1a; 给定一个 完美二叉树 &#xff0c;其所有叶子节点都在同一层&#xff0c;每个父节点都有两个子节点。二叉树定义如下&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧…

计组--总线

一、概念 总线是一组能为多个部件分时共享的公共信息传送线路。 共享是指总线上可以挂接多个部件&#xff0c;各个部件之间互相交换的信息都可以通过这组线路分时共享。 分时是指同一时刻只允许有一个部件向总线发送信息&#xff0c;如果系统中有多个部件&#xff0c;则它们…

qt常用控件1

QLabel QLabel用于显示文本或图像。不提供用户交互功能。标签的视觉外观可以通过多种方式进行配置&#xff0c;并且可用于为另一个小组件指定焦点助记键。 常用API介绍&#xff1a; 获取对应的文本信息&#xff1a; 设置对其方式&#xff1a; 设置能否进行换行 获取及设置标…

mysql面试题9:MySQL中的SQL常见的查询语句有哪些?有哪些对SQL语句优化的方法?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:MySQL中的SQL常见的查询语句有哪些? 常见的SQL查询语句包括: SELECT:用于从一个或多个表中获取数据。 FROM:指定要查询的表名或视图名。 WHER…

ssh爆破分析

1. 2.日志分析 1.系统账号信息 2.确认攻击情况 3.管理员登录情况 4.处理措施

网络基础入门(认识网络 网络传输 概念举例详解)

本篇文章主要是对网络初学的概念进行解释&#xff0c;可以让你对网络有一个大概整体的认知。 文章目录 一、简单认识网络 1、1 什么是网络 1、2 网络分类 二、网络模型 2、1OSI七层模型 2、1、1 简单认识协议 2、1、2 OSI七层模型解释 2、2 TCP/IP五层(或四层)模型 三、网络传…

【生物信息学】计算图网络中节点的中心性指标:聚集系数、介数中心性、度中心性

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. 生成邻接矩阵simulate_G: 2. 计算节点的聚集系数 CC(G): 3.计算节点的介数中心性 BC(G) 4. 计算节点的度中心性 DC(G) 5. 综合centrality(G) 6. 代…

《 新手》web前端(axios)后端(java-springboot)对接简解

文章目录 <font color red>1.何为前后端对接?2.对接中关于http的关键点2.1. 请求方法2.2. 请求参数设置简解&#xff1a; 3.对接中的跨域(CROS)问题**为什么后端处理跨域尽量在业务之前进行&#xff1f;**3.总结 1.何为前后端对接? “前后端对接” 是指前端和后端两个…

腾讯云中使用ubuntu安装属于自己的overleaf

在自己的云服务器上安装overleaf的需求是从写论文开始的&#xff0c;总担心自己的论文放在一个网站上被泄露&#xff0c;所以想要在自己的服务器上安装自己的overleaf&#xff0c;正好手边有一个云服务器&#xff0c;现在开始。 配置腾讯云 因为使用overleaf的优势就是在不同…

【小沐学前端】Node.js实现基于Protobuf协议的UDP通信(UDP/TCP)

文章目录 1、简介1.1 node1.2 Protobuf 2、下载和安装2.1 node2.2 Protobuf2.2.1 安装2.2.2 工具 3、node 代码示例3.1 HTTP3.2 UDP单播3.4 UDP广播 4、Protobuf 代码示例4.1 例子: awesome.proto4.1.1 加载.proto文件方式4.1.2 加载.json文件方式4.1.3 加载.js文件方式 4.2 例…

【知识梳理】多级页表的原理分析【地址形成过程】【扩充思考】

多级页表的地址形成过程 首先每个进程中都至少有一个页表&#xff08;段页式可以有多个页表&#xff09;&#xff0c;都有一个页表基地址寄存器&#xff08;PTBR&#xff09;&#xff0c;以下针对三级页表进行分析。 level1&#xff1a;PTBR代表的是一级页表的基地址&#xf…

链表经典面试题(三)

合并两个有序链表 1.题目2.图文分析3.代码实现 1.题目 2.图文分析 我们通过两个连接和指向的中介&#xff0c;我们可以将两个链表依次连接起来&#xff0c;并且当其中一个链表走完后&#xff0c;另一个链表剩余的值都会比另一个链表的值大&#xff0c;所以直接将指向中介指向他…

小谈设计模式(11)—模板方法模式

小谈设计模式&#xff08;11&#xff09;—模板方法模式 专栏介绍专栏地址专栏介绍 模板方法模式角色分类抽象类&#xff08;Abstract Class&#xff09;具体子类&#xff08;Concrete Class&#xff09;抽象方法&#xff08;Abstract Method&#xff09;具体方法&#xff08;C…