Vue 3响应式系统全解析:深入ref、reactive、computed、watch及watchEffect

一、ref与breactive

宏观角度看:

  • 1.ref 用来定义:基本类型数据、对象类型数据
  • 2.reactive 用来定义:对象类型数据

区别:

  • 【ref 】创建的变量必须使用.value
  • 【reactive】 重新分配一个新对象,会失去响应式(可以使用0biect.assign 去整体替换)。

使用原则:

  • 1.若需要一个基本类型的响应式数据,必须使用ref
  • 2.若需要一个响应式对象,层级不深,ref、reactive 都可以。
  • 3.若需要一个响应式对象,且层级较深,推荐使用reactive

二、toRefs与toRef

1.toRef

  • 作用:从 reactive 对象中提取单个属性,创建一个 ref。
  • 使用场景:当你需要对 reactive 对象的某个具体属性进行单独的响应式处理时。

基本用法

import { reactive, toRef } from 'vue';
const person = reactive({ name: 'John Doe' });
const nameRef = toRef(person, 'name');
console.log(nameRef.value); // John Doe

2.toRefs

  • 作用:将 reactive 对象转换为多个 ref 对象的集合。
  • 使用场景:适用于需要将整个 reactive 对象的多个属性分别作为 ref 处理的情况。

基本用法

import { reactive, toRefs } from 'vue';

const person = reactive({ name: 'John Doe', age: 30 });
const { name, age } = toRefs(person);
console.log(name.value); // John Doe
console.log(age.value);  // 30

结论

  • toRef 创建单个 ref,用于单个属性的响应式绑定。
  • toRefs 创建多个 ref,用于将整个对象的属性分别响应式绑定。
  • 选择使用 toRef 或 toRefs 取决于你需要对 reactive 对象执行的响应式操作的复杂性。

三、computed计算属性

计算属性是 Vue 3 中一种特殊的响应式变量,它根据其他响应式数据自动计算值。

基本用法

import { computed, ref } from 'vue';
const count = ref(0);
const doubledCount = computed(() => count.value * 2);

特点

  • 自动更新:当依赖的数据变化时,计算属性会自动重新计算。
  • 惰性计算:只有当依赖项变化时,计算逻辑才会执行。
  • 结果缓存:多次访问计算属性会得到相同的结果,而不会重复计算。

四、watch

作用:监视数据的变化(和 Vue2 中的 watch 作用一致)
特点:Vue3 中的 watch 只能监视以下四种数据:

1.ref 定义的数据。
2.reactive 定义的数据。
3.函数返回一个值(getter 函数)。
4.一个包含上述内容的数组。

watch 监听

⭐情况一

监视【ref】 直接写数据名即可,监视的是其 value 值的改变。

示例:

import { watch, ref } from 'vue';

const count = ref(0);

// 监视 ref 'count' 的变化
watch(count, (newValue, oldValue) => {
  console.log(`变化前:${oldValue} 变化后: ${newValue}`);
},{
    deep: true,       	// 深度监听 state 对象内部的变化
    immediate: true,  	// 当设置为 true 时,watch 会在开始监视后立即执行一次回调函数。
    flush: 'pre',     	// 控制副作用(如 DOM 更新)的刷新时机。可以是 'pre' 或 'post',或者一个包含这些值的数组。
    onTrack: () => {},  // 依赖项被追踪时调用
    onTrigger:() =>{},  // 依赖项变化时调用
    computed: true    	// 计算属性模式
});

⭐情况二

监视【ref】深层要手动开启深度监视

注意:
若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。

示例:

import { watch, ref } from 'vue';

const person = ref({ name: 'John', age: 30 });

// 监视 ref 'person' 的深层属性变化
watch(
  () => person.value, // 使用函数返回 ref 的 value,以确保每次都是最新的值
  (newValue, oldValue) => {
    // 回调函数会在 person 对象的属性变化时触发
    console.log(`变化前:${oldValue.name} 变化后:${newValue.name}`);
  },
  { deep: true } // 开启深度监视
);

在这个例子中:

  • person 是一个通过 ref 创建的响应式引用,它包含一个对象,该对象有 name 和 age 属性。
  • 使用 watch 函数并传入一个函数,该函数返回 person.value。这样做是因为我们需要监视 person 对象内部属性的变化,而不是 person 这个引用本身。
  • 参数 { deep: true } 开启了深度监视,这样 watch 就能够追踪到对象内部属性的变化。
  • 当 person 对象的 name 或 age 属性发生变化时,提供的回调函数会被触发。

注意事项

  • 当你监视 ref 定义的对象并开启深度监视时,newValue 和 oldValue 将代表对象内部发生变化的属性的新旧值。
  • 如果整个 ref 定义的对象被一个新的对象替换,那么 newValue 将是新对象,而 oldValue 将是旧对象。
  • 开启深度监视可能会带来性能上的考虑,因为它会增加 Vue 需要追踪的变化的数量。

⭐情况三

监视【reactive】定义的【对象类型】数据,默认开启深度监视(无法关闭)

示例:

import { reactive, watch } from 'vue';

// 使用 reactive 创建一个响应式对象
const person = reactive({
  name: 'John',
  details: {
    age: 30
  }
});

// 监视 reactive 对象的 'details.age' 属性
watch(
  () => person.details.age,
  (newValue, oldValue) => {
    console.log(`Age changed from ${oldValue} to ${newValue}`);
  }
);

在这个例子中:

  • person 是一个使用 reactive 创建的响应式对象,它包含一个名为 details 的属性,该属性本身也是一个对象,包含 age 属性。
  • 使用 watch 来监视 person.details.age 属性的变化。由于 reactive 默认进行深度监视,因此不需要额外的 deep 选项即可追踪到 details 对象内部的 age 属性变化。

注意事项

  • reactive 创建的响应式对象总是深度监视的,这意味着你无法关闭这个行为。
  • 当你使用 watch 来监视 reactive对象的属性时,即使属性是嵌套的,也不需要 deep 选项,因为深度监视是自动应用的。
  • 如果 reactive 对象的某个属性也是一个对象,并且你想要监视这个嵌套对象的属性,你可以直接使用 watch,并提供一个返回该嵌套属性的函数。

通过这种方式,Vue 3 的 reactive API 提供了一种直观且强大的方式来创建和管理响应式状态,同时 watch API 允许你监视这些状态的变化,无需担心监视的深度问题。

⭐情况四

监视响应式对象中的某个属性,且该属性是基本类型,要写成函数式
监视响应式对象中的某个属性,且该属性是对象类型,可以直接写,也能写函数,更推荐写函数


⭐结论:监视的要是对象里的属性,那么最好写函数式
⭐注意点:若是对象监视的是地址值,需要关注对象内部,需要手动开启深度监视。

基本类型属性的监视

当监视响应式对象中的基本类型属性时,推荐使用函数式的方式来访问该属性的值。这是因为基本类型的属性不会触发对象的重新分配,所以每次获取的都是最新的值。

示例:

import { watch, reactive } from 'vue';

const person = reactive({ name: 'John' });

// 使用函数式监视响应式对象中的 'name' 属性
watch(
  () => person.name,
  (newValue, oldValue) => {
    console.log(`变化前:${oldValue} 变化后:${newValue}`);
  }
);

在这个例子中,我们通过函数 () => person.name 来获取 person 对象的 name 属性的值。每次 watch 触发时,都会调用这个函数以确保获取到最新的 name 值。

对象类型属性的监视

当监视响应式对象中的对象类型属性时,可以直接写属性名,也可以使用函数式。推荐使用函数式,尤其是当你需要监视对象内部属性的变化时。

示例:

const person = reactive({ detail: { address: '123 Main St' } });

// 使用函数式监视 'detail' 对象内部的 'address' 属性
watch(
  () => person.detail.address,
  (newValue, oldValue) => {
    console.log(`变化前: ${oldValue} 变化后:${newValue}`);
  },deep: true } // 开启深度监视,以追踪对象内部属性的变化
);

在这个例子中,我们监视的是 person.detail.address。由于 address 是 detail 对象的属性,我们需要开启深度监视 { deep: true } 来确保当 address 发生变化时,watch 能够触发。
我们通过函数 () => person.name 来获取 person 对象的 name 属性的值。每次 watch 触发时,都会调用这个函数以确保获取到最新的 name 值。

⭐情况五:监视上述的多个数据

示例

import { watch, reactive, ref } from 'vue';

// 使用 reactive 创建一个响应式对象
const person = reactive({
  name: 'John',
  car: 'Toyota'
});

// 使用 ref 创建一个响应式引用
const age = ref(30);

// 监视 person 对象的 'name' 属性和 age 引用
watch([() => person.name, age], (newValues, oldValues) => {
  // newValues 和 oldValues 都是数组,分别包含新旧值
  console.log(`Name changed to ${newValues[0]}, Age changed to ${newValues[1]}`);
  // 如果只想监视 person.car 的变化,可以这样写:
  // watch([() => person.car, age], callback, options)
}, { deep: true });

在这个例子中:

  • 使用 reactive 创建了一个响应式对象 person,它包含 name 和 car 属性。
  • 使用 ref 创建了一个响应式引用age。 使用 watch 来监视 person.name 和 age。
  • 这里通过传递一个数组给 watch的第一个参数来实现同时监视多个数据源。数组中的每个元素都是一个返回要监视数据的函数或响应式引用。
  • newValues 和oldValues 参数都是数组,它们包含了所有监视数据源的新旧值。数组中每个元素的顺序与 watch 第一个参数中的顺序相对应。
  • { deep: true } 表示对 person 对象进行深度监视,这样可以确保当对象内部的属性变化时,也能触发 watch
    的回调函数。

注意事项

  • 当监视多个响应式数据源时,确保 newValues 和 oldValues 的索引与 watch 第一个参数中数据源的顺序相匹配。
  • 使用deep: true 选项可以确保当监视的对象或数组内部发生变化时,也能触发回调函数。

五、watchEffect

watchEffect 是 Vue 3 的一个工具,它用来观察你的数据。当你的数据变化时,它会做一些事情。

怎么用?
选择数据:首先,你需要有一些数据,比如一个数字。
告诉 watchEffect 观察这个数据。
决定数据变化时要做的事情:当这个数据变化时,watchEffect 会帮你做一个操作,比如打印信息。
例子
// 假设我们有一个数字,我们想观察它的变化
const count = 0;

// 使用 watchEffect 观察 count 的变化
watchEffect(() => {
// 当 count 变化时,打印 count 的新值
console.log(New value of count is: ${count});
});

// 如果你改变了 count 的值,上面的打印就会执行
停止观察
如果你后面不想观察了,可以告诉 watchEffect 停止。

const stop = watchEffect(() => {
// 逻辑
});

// 想要停止观察时,调用这个函数
stop();

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面试经典150题——二叉树展开为链表

​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 因为题目中提到:展开后的单链表应该与二叉树 先序遍历 顺序相同,那么我们是不是就可以先先序遍历,然后按照先序遍历的节点一个一个赋值? 其实最简单的思路就是用一个结构按顺序存…

加速大数据分析:Apache Kylin使用心得与最佳实践详解

Apache Kylin 是一个开源的分布式分析引擎,提供了Hadoop之上的SQL接口和多维分析(OLAP)能力以支持大规模数据。它擅长处理互联网级别的超大规模数据集,并能够进行亚秒级的查询响应时间。Kylin 的主要使用场景包括大数据分析、交互…

Web前端安全问题分类综合以及XSS、CSRF、SQL注入、DoS/DDoS攻击、会话劫持、点击劫持等详解,增强生产安全意识

前端安全问题是指发生在浏览器、单页面应用、Web页面等前端环境中的各类安全隐患。Web前端作为与用户直接交互的界面,其安全性问题直接关系到用户体验和数据安全。近年来,随着前端技术的快速发展,Web前端安全问题也日益凸显。因此&#xff0c…

Altair:Python数据可视化库的魅力之旅

目录 一、引言 二、Altair概述 三、Altair的核心特性 1.声明式语法 2.丰富的图表类型 3.交互式与响应式 4.无缝集成 四、案例与代码实践 案例一:使用Altair绘制折线图 案例二:使用Altair绘制热力图 五、新手入门指南 1.安装与导入 2.数据准…

Nacos服务注册中心

1.引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>2.application.properties中配置 # 应用名称 spring.application.namenacos-aserver…

美国洛杉矶服务器的特点

美国洛杉矶的服务器提供多种优质的托管服务&#xff0c;具有较好的网络连接速度和稳定性。以下是一些洛杉矶服务器的特点和服务&#xff0c;rak小编为您整理发布。 1. **地理位置优势**&#xff1a;位于美国西海岸的洛杉矶机房离中国相对较近&#xff0c;这有助于减少延迟&…

指针专题(4)【qsort函数的概念和使用】

1.前言 上节我们学习了指针的相关内容&#xff0c;本节我们在有指针的基础的条件下学习一下指针的运用&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 2.回调函数 我们既然已经学习了指针的相关基础&#xff0c;那么我们此时就可以用指针来实现回调函数 而回…

如何在在wordpress安装百度统计

前言 看过我的往期文章的都知道&#xff0c;我又建了一个网站&#xff0c;这次是来真的了。于是&#xff0c;最近在查阅资料时发现&#xff0c;有一款免费的软件可以帮我吗分析网站数据。&#xff08;虽然我的破烂网站压根没人访问&#xff0c;但是能装上的都得上&#xff0c;…

python爬虫 - 爬取html中的script数据(爬取 zum.com新闻)

文章目录 1. 分析页面内容数据格式2. 使用re.findall方法&#xff0c;编写爬虫代码3. 使用re.search 方法&#xff0c;编写爬虫代码 1. 分析页面内容数据格式 &#xff08;1&#xff09;打开 https://zum.com/ &#xff08;2&#xff09;按F12&#xff08;或 在网页上右键 --…

免 Administrator 权限安装软件

以欧路词典为例, 从官网下载的安装包 https://www.eudic.net/v4/en/app/download 直接运行会弹出 UAC 提示需要管理员权限. 一个词典而已, 为啥要管理员权限呢? 答案是安装程序默认使用的安装路径是 C:\Program Files\ 这就不难理解了. 对于这种不需要其他额外权限的软件, 可以…

以赛促学、生态共建 | 软通动力子公司鸿湖万联成功举办基于x86架构的OpenHarmony应用生态挑战赛

近日&#xff0c;由开放原子开源基金会、央视网、江苏省工业和信息化厅、无锡市人民政府、江苏软件产业人才发展基金会、苏州工业园区、无锡高新区等共同承办&#xff0c;鸿湖万联参与共建的“基于x86架构的OpenHarmony应用生态挑战赛”决赛路演在无锡圆满落幕。本次挑战赛历时…

【THM】Linux Privilege Escalation(权限提升)-初级渗透测试

介绍 权限升级是一个旅程。没有灵丹妙药,很大程度上取决于目标系统的具体配置。内核版本、安装的应用程序、支持的编程语言、其他用户的密码是影响您通往 root shell 之路的几个关键要素。 该房间旨在涵盖主要的权限升级向量,并让您更好地了解该过程。无论您是参加 CTF、参加…

【C++学习】STL之空间配置器之一级空间配置器

文章目录 &#x1f4ca;什么是空间配置器✈STL 提供六大组件的了解&#x1f440;为什么需要空间配置器&#x1f44d;SGI-STL空间配置器实现原理&#x1f302;一级空间配置器的实现 &#x1f4ca;什么是空间配置器 空间配置器&#xff0c;顾名思义就是为各个容器高效的管理空间…

录制课程用什么软件好?这2款软件让你脱颖而出

在当今这个信息化快速发展的时代&#xff0c;录制课程已经成为了一种常见的教学手段。无论是高校教师、培训师还是网络教育工作者&#xff0c;都需要借助一些软件来录制高质量的课程。那么&#xff0c;录制课程用什么软件好呢&#xff1f;接下来&#xff0c;本文将介绍两种常见…

DxO Nik Collection 6.10.0 8套滤镜胶片插件套件mac/win

DxO Nik Collection 6是一款专为摄影师和图像创作者打造的强大后期处理工具。无论是专业摄影师还是业余爱好者&#xff0c;它都能为您的照片带来前所未有的提升。 这款软件集合了众多经典的Nik滤镜插件&#xff0c;如Color Efex Pro、Silver Efex Pro等&#xff0c;以及新增的P…

微信抽奖活动怎么做_微信抽奖大狂欢

随着科技的飞速发展&#xff0c;微信已经成为我们生活中不可或缺的一部分。它不仅仅是一个简单的通讯工具&#xff0c;更是一个集社交、购物、娱乐等多种功能于一体的平台。今天&#xff0c;我们为大家带来了一场别开生面的微信抽奖活动&#xff0c;让你在享受乐趣的同时&#…

Linux CentOS 7中Nginx 1.8.0 安装SSL证书

文章目录 前言一、创建一个文本文件&#xff0c;将每个证书的内容复制并粘贴到文件中二、将证书文件和私钥上传服务器三、编辑nginx的配置文件四、重新载入nginx配置文件五、使用浏览器访问自己的域名测试证书是否成功即可六、服务器证书的备份与恢复注意 前言 要在Nginx中安装…

面试题集中营—分布式共识算法

分布式共识算法目标 分布式主要就是为了解决单点故障。一开始只有一个服务节点提供服务&#xff0c;如下图所示。那么如果服务节点挂了&#xff0c;对不起等着吧。 为了服务的高可用性&#xff0c;我们一般都会多引入几个副节点当备份&#xff0c;当服务节点挂了&#xff0c;就…

羊大师:夏季羊奶的好处有哪些?

夏季羊奶的好处主要包括以下几点 1.增强免疫力&#xff1a;羊奶中的钙元素丰富&#xff0c;能有效为身体补充营养物质&#xff0c;增强自身的免疫能力。羊奶还富含上皮细胞生长因子&#xff08;EGF&#xff09;&#xff0c;对人体鼻腔、咽喉、血管、肠胃等黏膜有良好的修复作用…

day83 AJAX

1什么是AJAX AJAX语法 AJAX Asynchronous JavaScript and XML 异步js和XML 实现页面某一部份更新&#xff0c;无需服务器转发或重定向 1 $.ajax() 语法: $.ajax( { "url" : "url&qu…
最新文章