探究Vue3中的Composition API:优化组件逻辑的新利器

一、toRef函数

在 Vue 3.0 中,引入了一种新的响应式 API,即 toReftoRef 函数可以将一个普通值转换为响应式引用类型,这样就可以在模板中直接使用这个响应式引用类型的属性,并且当该属性发生变化时,视图会自动更新。

<template><div><h2>年龄:{{ age }}</h2><h2>原值:{{person.age }}</h2><button  @click="age++;console.log(age)">年龄增加</button></div>
</template><script>
import { reactive} from 'vue';export default {name: 'TodoList',setup() {// 使用 ref 创建响应式数据const person = reactive({name: 'JingYu',age: 18,})// 暴露数据和方法给模板使用return {age:person.age,person,};},
};
</script>

通过控制台打印输出的内容和页面的变化,我们可以观察到,age的值一直在变化,但其不是响应式的,所以页面没有随着值的变化而更新视图。这是因为这种写法就好比我们定义了一个新的变量,将person.age的值18赋值给这个变量。但这个变量并不是响应式的。
image.png

这时我们就可以通过toRef将其转换为响应式的

    const person = reactive({name: 'JingYu',age: 18,})// 暴露数据和方法给模板使用let age=toRef(person,'age')console.log(age)return {age,person,};

细心地同学可能从上面的代码中注意到了一点,我在页面中还显示了一个person.age的值。

  <div><h2>年龄:{{ age }}</h2><h2>原值:{{person.age }}</h2><button  @click="age++;console.log(age)">年龄增加</button></div>

为什么要展示它的值呢,看了将person中age属性单独转换成一个单独的响应式引用之后,你就会发现,页面展示的两个值都会随之改变。

image.png

如果你不小心写成了这种形式

let age=toRef(person.age)

你就会惊奇的发现,页面展示的person.age不会随之改变了.

image.png

这里需要注意一下两种写法的区别:

1.当你使用toRef(person, 'age')时,你是在告诉Vue你希望将person对象的age属性转换为一个单独的响应式引用。这意味着当person.age的值发生变化时,引用的值也会相应地更新。
2.toRef(person.age)是将person.age直接转换为响应式引用,而不是从person对象中获取对age属性的引用。这意味着当你修改person.age的值时,引用的值不会自动更新。

二、toRefs函数

torefstoRef的作用是一样的,只不过toRefs是将一个对象的所有属性都变为单独的响应式。

    setup() {// 使用 ref 创建响应式数据const person = reactive({name: 'JingYu',age: 18,})// 暴露数据和方法给模板使用return {...toRefs(person)};},

通过使用扩展运算符将person对象的所有属性展开返回。成功实现单个属性的响应式。

image.png

三、shallowReactive 与 shallowRef

shallow是浅的、浅显的意思。

顾名思义:

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)
      <h2>年龄{{ person.age }}</h2><h2>薪资{{ person.job.salary }}</h2><button  @click="person.age++;console.log(person.age,'---')">年龄增加</button><button  @click="person.job.salary++;console.log(person.job.salary)">薪资增加</button>const person = shallowReactive({name: 'JingYu',age: 18,job:{name:'前端开发',salary:8}})

我们可以观察到年龄是响应式的,而第二层的属性薪资就不是响应式的了。
image.png

  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。
      <h2>年龄{{ person.age }}</h2><button  @click="person.age++;console.log(person.age,'---')">年龄增加</button>const person = shallowRef({name: 'JingYu',age: 18,})

虽然person.age的值改变了,但数据并不是响应式的,所以页面视图没有更新。
image.png

  • 使用场景

1.如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。

2.如果有一个对象数据,后续功能不会修改该对象中的属性,而是用新的对象来替换 ===> shallowRef。

解释一下这句话:

      <h2>年龄{{ person.age }}</h2><button  @click="person={age:20}">年龄改变</button>

此时点击按钮页面会变为20,因为我们改变的不是x里面的属性,而是将整个person对象重新赋值,person是响应式。的。

四、readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)。

如果使用readonly修饰对象person,所有的属性都不能修改了。当你修改时控制台还会输出警告.

<template><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><h2>薪资:{{job.j1.salary}}K</h2><button @click="name+='~'">修改姓名</button><button @click="age++">增长年龄</button><button @click="job.j1.salary++">涨薪</button>
</template><script>import {reactive,toRefs,readonly} from 'vue'export default {name: 'HelloWorld',setup(){//数据let person = reactive({name:'张三',age:18,job:{j1:{salary:20}}})person = readonly(person)//返回一个对象(常用)return {...toRefs(person)}}}
</script>

image.png

如果使用shallowReadonly修饰对象person,只有最外层的不能修改了。salary还是可以修改的。

<template><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><h2>薪资:{{job.j1.salary}}K</h2><button @click="name+='~'">修改姓名</button><button @click="age++">增长年龄</button><button @click="job.j1.salary++">涨薪</button>
</template><script>import {reactive,toRefs,shallowReadonly} from 'vue'export default {name: 'HelloWorld',setup(){//数据let person = reactive({name:'张三',age:18,job:{j1:{salary:20}}})person = shallowReadonly(person)//返回一个对象(常用)return {...toRefs(person)}}}
</script>

image.png

五、toRaw 与 markRaw

  • toRaw是一个用于将响应式对象转换为其原始非响应式版本的函数。

    toRaw函数接受一个响应式对象作为参数,并返回该对象的原始非响应式版本。它实际上返回了一个指向原始对象的引用,而不是创建一个新的对象。
import { reactive, toRaw } from 'vue' 
const originalObj = { foo: 'bar' } 
const reactiveObj = reactive(originalObj) 
console.log(reactiveObj.foo) // 输出 "bar" 
const rawObj = toRaw(reactiveObj) 
rawObj.foo = 'baz' // 修改原始对象 
console.log(reactiveObj.foo) // 输出 "baz"
  • markRaw是Vue3中用于标记一个对象,使其永远不会转换为响应式对象的函数。

有些值不应被设置为响应式的,例如复杂的第三方类库或Vue组件对象。在这种情况下,我们可以使用markRaw函数。

import { reactive, markRaw } from 'vue' 
const originalObj = { foo: 'bar' } 
const reactiveObj = reactive(originalObj) 
console.log(reactiveObj.foo) // 输出 "bar" 
const rawObj = markRaw(originalObj) 
console.log(isReactive(reactiveObj)) // 输出 "true" 
console.log(isReactive(rawObj)) // 输出 "false" 
// 尝试将rawObj转换为响应式对象 
const reactiveRawObj = reactive(rawObj) 
console.log(isReactive(reactiveRawObj)) // 输出 "false"

在上面的示例中,我们首先使用reactive函数将originalObj转换为一个响应式对象reactiveObj。然后,我们使用markRaw函数将originalObj转换为其非响应式版本rawObj。我们使用isReactive函数验证了reactiveObj是响应式对象,而rawObj不是。最后,我们尝试将rawObj转换为响应式对象,但是通过isReactive函数验证后发现,转换并未生效。

六、provide 与 inject

在Vue 3中,provideinject是用于跨层级组件通信的两种方法。

provide方法允许父组件向下传递数据给子组件。provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。

inject方法允许子组件从父组件中获取传递的数据。它接收两个参数:一个是需要注入的键值,另一个是默认值。如果父组件没有提供该键值,则inject方法将返回默认值。

具体用法

祖组件中:

setup(){......let car = reactive({name:'奔驰',price:'40万'})provide('car',car)......
}

后代组件:

setup(props,context){......const car = inject('car')return {car}......
}

响应式数据的判断

  • isRef: 检查一个值是否为一个 ref 对象
  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

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

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

相关文章

兵者多诡(HCTF2016)

环境:https://github.com/MartinxMax/CTFer_Zero_one 题目简介 解题过程 登录首页 提交png图片上传抓包&#xff0c;可以看到是向upload文件提交数据 在fp参数中尝试伪协议读取home.php文件 http://127.0.0.1:88/HCTF2016-LFI/home.php?fpphp://filter/readconvert.base64…

Mybatis的关系关联配置

前言 MyBatis是一个流行的Java持久化框架&#xff0c;它提供了一种简单而强大的方式来映射Java对象和关系数据库之间的数据。在MyBatis中&#xff0c;关系关联配置是一种用于定义对象之间关系的方式&#xff0c;它允许我们在查询数据库时同时获取相关联的对象。 在MyBatis中&…

第17章 站点构建

mini商城第17章 站点构建 一、课题 站点构建 二、回顾 1、Gateway限流 2、Nginx限流 3、Redis集群应用 4、缓存灾难处理 三、目标 1、Sentinel Sentinel介绍 Sentinel核心功能 Sentinel集成Gateway Sentinel控制台 2、Lvs+Nginx集群 Lvs负载均衡模式 NAT模式 TUN模式 …

实现在外网SSH远程访问内网树莓派的详细教程

文章目录 如何在局域网外SSH远程访问连接到家里的树莓派&#xff1f;如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar4.2 cpolar进行token认证4.3 配置cpol…

HCIA自学笔记01-冲突域

共享式网络&#xff08;用同一根同轴电缆通信&#xff09;中可能会出现信号冲突现象。 如图是一个10BASE5以太网&#xff0c;每个主机都是用同一根同轴电缆来与其它主机进行通信&#xff0c;因此&#xff0c;这里的同轴电缆又被称为共享介质&#xff0c;相应的网络被称为共享介…

15:00面试,15:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%,…

算法通关村第12关【白银】| 字符串经典问题

一、反转问题 1.反转字符串 思路&#xff1a;双指针&#xff0c;反转数组一个套路 class Solution {public void reverseString(char[] s) {int l 0;int r s.length -1;while(l<r){char c s[l];s[l] s[r];s[r] c;l;r--;}} } 2.k个一组反转 思路&#xff1a;每k个进行…

第14章_瑞萨MCU零基础入门系列教程之QSPI

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

【leetcode 力扣刷题】删除字符串中的子串or字符以满足要求

删除字符串中的子串或者字符以满足题意要求 1234. 替换子串得到平衡字符串680. 验证回文串917. 仅仅反转字母 1234. 替换子串得到平衡字符串 题目链接&#xff1a;1234. 替换子串得到平衡字符串 题目内容&#xff1a; 题目中给出了平衡字符串的定义——只有’Q’&#xff0c;…

彻底掌握Protobuf编码原理与实战

目录 1.类型2.VARINT 2.1 无符号数2.2 有符号数3.定长 3.1 I64类型3.2 I32类型4.LEN5.代码 学习这些有什么用&#xff1f; - 如果你是后端开发者&#xff0c;掌握这个对工作非常有用 - 如果你是求职者&#xff0c;面试时可以临危不惧 1.类型 最近看到有直接操作wire type相关的…

React+antd实现可编辑单元格,非官网写法,不使用可编辑行和form验证

antd3以上的写法乍一看还挺复杂&#xff0c;自己写了个精简版 没用EditableRowCell的结构&#xff0c;也不使用Context、高阶组件等&#xff0c;不使用form验证 最终效果&#xff1a; class EditableCell extends React.Component {state {editing: false};toggleEdit () &…

系统软件启动过程

实验一&#xff1a;系统软件启动过程 参考 重要文件 调用顺序 1. boot/bootasm.S | bootasm.asm&#xff08;修改了名字&#xff0c;以便于彩色显示&#xff09;a. 开启A20 16位地址线 实现 20位地址访问 芯片版本兼容通过写 键盘控制器8042 的 64h端口 与 60h端口。b.…

Selenium自动化测试框架常见异常分析及解决方法

01 pycharm中导入selenium报错 现象: pycharm中输入from selenium import webdriver, selenium标红 原因1: pycharm使用的虚拟环境中没有安装selenium, 解决方法: 在pycharm中通过设置或terminal面板重新安装selenium 原因2: 当前项目下有selenium.py,和系统包名冲突导致, …

Amazon Aurora MySQL 和 Amazon RDS for MySQL 集群故障转移和只读实例扩容时间测试

01 测试背景 Amazon Aurora MySQL 是与 MySQL 兼容的关系数据库&#xff0c;专为云而打造&#xff0c;性能和可用性与商用数据库相当&#xff0c;成本只有其 1/10。 Amazon RDS for MySQL 让您能够在云中更轻松设置、操作和扩展 MySQL 部署。借助 Amazon RDS&#xff0c;您可以…

SpringBoot环境MongoDB分页+去重+获取去重后的原始数据

最近有个比较复杂的MongoDB查询需求&#xff0c; 要求1&#xff1a;获取最近订单表中的请求参数信息&#xff0c;并需要按照请求参数中的账号进行去重 要求2&#xff1a;数据量可能比较大&#xff0c;因此需要做分页查询 研究了大半天&#xff0c;终于搞出了解决方案&#xff0…

MySQL触发器详解保证入土

文章目录 简介一、MySQL触发器基础触发器分类基础常用关键字1. 定义触发器2. 创建和删除触发器3. 执行时机和条件 二、MySQL触发器的使用场景1. 数据完整性约束插入触发器更新触发器删除触发器 2. 数据变更日志的记录与追踪3. 触发器与存储过程的对比与选择 三、触发器的性能和…

C++学习笔记(重载、类)

C 1、函数重载2、类2.1、类的方法和属性2.2、类的方法的定义2.3、构造器和析构器2.4、基类与子类2.5、类的public、protected、private继承2.6、类的方法的重载2.7、子类方法的覆盖2.8、继承中的构造函数和析构函数 1、函数重载 函数重载大概可以理解为&#xff0c;定义两个名…

C语言实现三字棋

实现以下&#xff1a; 1游戏不退出&#xff0c;继续玩下一把&#xff08;循环&#xff09; 2应用多文件的形式完成 test.c. --测试游戏 game.c -游戏函数的实现 game.h -游戏函数的声明 (2)游戏再走的过程中要进行数据的存储&#xff0c;可以使用3*3的二维数组 char bor…

idea VCS配置多个远程仓库

Idea VCS配置多个远程仓库 首先要有两个或多个不同远程仓库地址 idea 添加数据源 查看推送记录 添加数据源 ok之后填写账号密码 推送本地项目 选择不同远程地址 push 查看不同远程地址的 不同分支的 推送记录 不期而遇的温柔&#xff1a; 应用开源架构进行项目开发&#xff0…

Java版企业电子招标采购系统源码—企业战略布局下的采购寻源

功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外部供…