从Vue2到Vue3【三】——Composition API(第三章)

news2024/12/26 16:43:22

系列文章目录

内容链接
从Vue2到Vue3【零】Vue3简介
从Vue2到Vue3【一】Composition API(第一章)
从Vue2到Vue3【二】Composition API(第二章)
从Vue2到Vue3【三】Composition API(第三章)
从Vue2到Vue3【四】Composition API(第四章)

文章目录

  • 系列文章目录
  • 前言
  • 一、shallowReactive 与 shallowRef
  • 二、readonly 与 shallowReadonly
  • 三、toRaw 与 markRaw
  • 总结


前言

随着Vue 3的发布,我们迎来了一套强大且令人兴奋的组合式API,这为开发者带来了更多灵活性和可维护性。Vue 3的组合式API不仅改变了我们编写Vue组件的方式,还引入了一些新的组件和一些小的但实用的改变。在这篇文章中,我们将深入探讨Vue 3的组合式API,并介绍一些引人注目的新组件和改变,让我们一起开始这个令人兴奋的学习之旅吧!

一、shallowReactive 与 shallowRef

  • shallowReactive:

    • shallowReactive函数用于创建一个浅响应式对象,它只会对对象的第一层属性进行响应式处理,而不会递归地对嵌套的属性进行深层次响应式处理。
    • 这在某些情况下可以提高性能和减少内存消耗,特别是当对象的嵌套层次很深或者对象非常大时
    • 适用场景:当需要对一个大型对象进行响应式处理,但只关心对象的第一层属性变化时,可以使用shallowReactive来避免深层次的响应式处理
import {shallowReactive} from 'vue'
export default {
	name: 'App',
	setup(){
		let data = ({
		name: 'John',
		age: 25,
		address: {
			street: 'Main St',
			city: 'New York'
			}
		})
		let data1 = shallowReactive(data)
		return {
				data1
		}
	}
}

由于shallowReactive函数创建的是一个浅响应式对象,所以当改变data1.name时,会触发响应
但当修改data1.address.street时,就不会触发响应 (shallowReactive:只处理对象最外层属性的响应式)

  • shallowRef:

    • shallowRef函数用于创建一个浅响应式引用它只会对值的第一层进行响应式处理,而不会递归地对嵌套的值进行深层次响应式处理 ===》只处理基本数据类型的响应式, 不进行对象的响应式处理
    • 类似于shallowReactive,这在某些情况下可以提高性能和减少内存消耗
    • 适用场景:当需要对一个值进行响应式处理,但只关心值的第一层变化时,可以使用shallowRef来避免深层次的响应式处理。
<template>
	{{name1}} 
	<button @click="name1 = '前端百草阁'">点我修改name</button>
	<br>
	{{ data1.address.street }}
	<button @click="data1.address.street = '前端百草阁'">点我修改stree</button>
</template>

<script>
import {shallowRef} from 'vue'
export default {
	name: 'App',
	setup(){
		let name = 'John'
		let data = ({
		age: 25,
		address: {
			street: 'Main St',
			city: 'New York'
			}
		})
		let data1 = shallowRef(data)
		let name1 = shallowRef(name)

		console.log(data1.value,name1.value);  // 在setup中操作数据时 要加.value
		return {
			data1,
			name1
		}
	}
}
</script>

在这里插入图片描述
这里小伙伴们注意一个点,无论是操作数据还是使用数据都和ref、reactive一样,ref在操作数据时要加.value才能拿到对应的值

通过使用shallowReactive和shallowRef,可以根据具体的需求选择性地进行响应式处理,避免不必要的性能开销。在处理大型对象或嵌套层次较深的数据时,这些函数可以提供更好的性能和内存利用率。

二、readonly 与 shallowReadonly

  • readonly
    • 让一个响应式数据变为只读的(深只读
    • 将整个对象及其嵌套的属性设置为只读的场景,保护某些数据不被修改
<script>
import { ref, reactive, toRefs,readonly } from "vue";
export default {
  name: "deMO",
  setup() {
    //数据
    let sum = ref(0);
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });

    person = readonly(person);
    sum = readonly(sum)

    return {
      sum,
      ...toRefs(person),
    };
  },
};
</script>

由于这里使用的是readonly深只读,所以sum以及person的每一个属性都无法被修改

  • shallowReadonly
    • 让一个响应式数据变为只读的(浅只读
    • 将对象数据的第一层属性设置为只读
<script>
import { ref, reactive, toRefs,shallowReadonly } from "vue";
export default {
  name: "deMO",
  setup() {
    //数据
    let sum = ref(0);
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });
    
    person = shallowReadonly(person)
    sum = shallowReadonly(sum)
    
    return {
      sum,
      ...toRefs(person),
    };
  },
};
</script>

由于person设置了浅只读,所以person中的name属性值不能改变,但是person中的j1里的属性是可以修改的

  • 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
  • 如果有一个对象数据,后续功能不会修改该对象中的属性 ===> shallowRef。

通过使用readonly和shallowReadonly,我们可以根据具体的需求选择性地进行保护数据的可写性,从而提高代码的可靠性和安全性。

这里注意无论是深只读还是浅只读都不会影响到原先的响应式数据,所以最好用方法返回的只读数据覆盖掉之前的响应式数据 ,更加安全
什么意思呢? 在进行只读操作后,原先的响应式数据并不会发生变化,并且当你再次修改这个响应式数据时,只读的数据会跟着变化

举个例子,大家注意看

  setup() {
    let car = reactive({ name: "奔驰", price: "40W" });
    let car1 = readonly(car)
    car.name = '宝马'
    // car1.name = '劳斯莱斯'   car1的值为只读不能修改 
    console.log(car1,car);
    
    return { };
  },
};

这里car1是car的只读数据,当car的值发生变化时,car1的值对应着也会变化,但是car1的值不能直接修改
在这里插入图片描述
car1 的值直接修改不起作用,并且会报错
在这里插入图片描述

三、toRaw 与 markRaw

  • toRaw函数:

    • 作用:将一个由reactive生成的响应式对象转为普通对象
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新
<script>
	import {ref,reactive,toRaw} from 'vue'
	export default {
		name: 'Demo',
		setup(){
			//数据
			let person1 = ref({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})
			let person = reactive({
				name:'张三',
				age:18,
				job:{
					j1:{
						salary:20
					}
				}
			})

				const p = toRaw(person) // person是reactive生成的响应式对象
				p.age++      // 普通对象的值可以改变 但是不再引起页面更新
				console.log(p)  // 转换完后的p就是一个普通对象

				const p1 = toRaw(person1.value) 
				p1.age++      
				console.log(p)  // 转换完后的p就是一个普通对象
			
			return {
				sum,
				person
			}
		}
	}
</script>

这里注意笔者为什么要写两个person,不是说toRaw的作用是把一个由reactive生成的响应式对象转换为一个普通对象么?
为什么这里还有一个由ref生成的响应式对象呢

这得透过问题看本质,ref定义一个响应式对象内部求助了reactive,所以person1.value实质上也是一个Proxy对象,所以在转换成普通对象时,要toRaw(person1.value)

再注意一个问题,大家有没有一个疑问,我把person转成了普通对象并且用一个p接收转换完后的对象,那么person自己本身有变化么

实验才能出真知,由于好奇大家才在不停的进步,尝试后发现响应式对象转换为普通对象时,并不会影响先前的响应式对象,换句话说就是person依然是响应式对象,修改它,页面依旧会发生变化
还有一个点

  setup() {
    let car = reactive({ name: "奔驰", price: "40W" });
    let car2 = toRaw(car)
    // car.name = '宝马'
    car2.name = '劳斯莱斯' 
    console.log(car,car2);
    }

在这里插入图片描述

修改car 会改变car的值,修改car2的值同时car的值也会变

  • markRaw:
    • 作用:标记一个对象,使其永远不会再成为响应式对象
    • 应用场景:
      1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
      2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

      响应式追踪和更新是一个相对开销较大的操作。将复杂的第三方类库或大型对象设置为响应式的,会导致每次更新时都需要深度遍历对象并触发更新,对性能有一定影响。如果这些值不需要在视图中展示或参与响应式计算,将其设置为非响应式可以提高性能。

<script>
<script>
import { ref, reactive, toRefs, markRaw } from "vue";
export default {
  name: "deMo",
  setup() {
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20,
        },
      },
    });

      let car = { name: "奔驰", price: 40 };
      person.car = markRaw(car);  // 将一个标记过的对象添加到person的属性中

      person.car.price++;  // 数据会变化  但是页面不再更新(没有响应式)
      console.log(person.car.price);

    return {
      person,
      ...toRefs(person), // 普通对象被标记过后 再也无法变成响应式的
    };
  },
};
</script>

这里注意一个点 如果说person已经是一个响应式对象了,这时及时往他身上添加一个普通的属性,这个属性也具有响应式

      let car = { name: "奔驰", price: 40 };
      person.car = car;  // 将一个普通对象添加到person的属性中

      person.car.price++;  // 数据会变化  页面会更新(有响应式)
      console.log(person.car.price);

通过使用toRaw和markRaw,我们可以有更灵活的控制对象的响应式特性。toRaw使我们能够获取响应式对象的非响应式原始值。markRaw则可以将对象标记为非响应式,避免不必要的响应式追踪和更新。这些工具在一些特定场景下提供了更好的性能和控制的选择。

总结

本文讲解了vue3组合式API中的 shallowReactive 与 shallowRefreadonly 与 shallowReadonlytoRaw 与 markRaw的用法以及注意事项,欢迎大家订阅本系列文章,干货满满!

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

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

相关文章

webrtc QOS方法二.4(flexfec 实现可优化点)

一、冗余报文和媒体报文组织结构优化点 以单帧10个媒体报文&#xff0c;冗余度20%为例。这里webrtc输出要有10个媒体包2个冗余包。webrtc输出的报文序列如下&#xff1a; 代码实现如下&#xff1a; UlpfecGenerator::AddPacketAndGenerateFec&#xff1a;攒够足够的帧 Forwar…

使用springboot进行后端开发100问

properties和yaml文件怎么互转 安装插件 properties文件和yaml文件区别 properties 文件通过“.”和“”赋值&#xff0c;值前不加空格&#xff0c;yaml通过“:”赋值&#xff0c;值前面加一个空格&#xff1b;yaml文件缩进用空格&#xff1b; properties只支持键值对&#x…

C++实现LRU(逐句讲解)

使用双向链表解决此问题&#xff0c;因为双向链表可以很容易的获取到头结点和尾结点。题目要求 get 和 put 要在O(1)的时间复杂度下运行&#xff0c;很显然要用set或map。根据题意&#xff0c;应使用map。 unordered_map<int,Node*> cache; map->first为Node中的key&a…

查看RabbitMQ日志---trace插件的使用

我的RabbitMQ是安装在docker里面的 所以我以下的方法都是根据这个路径去操作的 如果RabbitMQ安装在其他地方 请自行百度 1. 显示正在运行的RabbitMQ容器的名称或ID&#xff1a; docker ps这将启动所有正在运行的 Docker 容器&#xff0c;并包含 RabbitMQ 容器的信息。 使用…

【Docker】Docker的数据管理

目录 一、Docker 的数据管理1.1数据卷1.2 数据卷容器1.3端口映射1.4容器互联&#xff08;使用centos镜像&#xff09; 二、Docker镜像的创建2.1基于现有镜像创建2.2&#xff0e;基于本地模板创建2.3 基于Dockerfile 创建联合文件系统&#xff08;UnionFS&#xff09;镜像加载原…

【云原生】Docker网络及Cgroup资源控制

一、Docker网络 1.docker网络实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Container-IP&#xff0c;同时Docker网桥是每个容器的默认网关。…

【Linux网络】 网络套接字(二)socket编程_UDP网络程序

目录 socket 编程接口socket 常见的APIsockaddr结构 UDP网络程序简单例子服务端代码编写服务端创建套接字服务端绑定运行服务器测试启动服务端 客户端代码编写客户端创建套接字启动客户端本地测试INADDR_ANY服务端接收信息发回到客户端如何进行网络测试 socket 编程接口 socke…

【机器学习】吃瓜教程 | 西瓜书 + 南瓜书 (1)

文章目录 一、绪论1、什么是机器学习&#xff1f;2、基本术语3、假设空间4、归纳偏好5、发展历程 二、模型评估与选择A、一种训练集一种算法2.1 经验误差 与 过拟合2.2 评估方法a) 留出法b) 交叉验证法c) 自助法d) 调参与最终模型 2.3 性能度量a) 错误率与精度b) 查准率、查全率…

RT-Thread快速入门-内核移植

1RT-Thread快速入门-内核移植 RT-Thread 快速入门系列前面的文章介绍了内核相关的知识&#xff0c;以及内核提供的接口函数和如何使用。 本篇文章主要介绍如何将 RT-Thread 内核移植到某个硬件平台之上。移植分为两部分&#xff1a; CPU 架构移植 BSP 移植 也就是将 RT-Th…

MySQL第二课表的增删插改

&#x1f49b; 后端进行的表的操作增删查改 现在是建了一个成绩表&#xff0c;注意哈。 decimal(2,1). 2是M表示有两个有效数字长度&#xff0c;1是D的长度&#xff0c;即小数点后有一位(10分制) &#x1f493;开始 1.增加&#xff1a; insert into 表名 values(值&#xff0…

安装VS Code 和 MiKTeX开发环境

下载&#xff1a; Getting MiKTeX 然后以管理员方式运行安装。 配置VS Code 之后配置VS Code&#xff0c;选择扩展&#xff08;两个位置都可以&#xff09;&#xff0c;然后搜索Latex&#xff1a; 然后打开设置&#xff1a; 这样就打开了setting.json文件&#xff0c; 然后…

SQL注入之Oracle环境搭建

SQL注入之Oracle环境搭建 前言 Oracle Database&#xff0c;又名Oracle RDBMS&#xff0c;或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是世界上流行的关系数据库管理系统&#xff0c;系统可移植性…

gitlab上传新项目全过程

gitlab上传新项目全过程 一、前期准备1.1 gitlab配置1.2 gitlab安装1.3 需要在gitlab上新建一个空项目 二、本地操作2.1 gitlab上传新项目全过程2.2 gitlab将远程项目拉取到本地全过程 三、常见问题及解决四、常用命令4.1 代码更新提交命令4.2 其他指令 一、前期准备 1.1 gitl…

less中引入自定义字体文件

前言 一般做后台管理系统UI没有影响要求可以不使用自定义字体。但是在大屏项目中&#xff0c;高度自定义化&#xff0c;就肯定需要UI导出字体文件&#xff0c;然后放到服务器上或者是我们项目文件中&#xff0c;我们前端引入后在页面中使用。 下面以放在项目文件中为例。 各…

【linux】五种IO模型与非阻塞IO

文章目录 一、IO的概念二、IO的五种模型2.1 概念2.2 对比五种IO 三、非阻塞IO3.1 fcntl文件描述符控制3.2 以非阻塞轮询方式读取标准输入 一、IO的概念 前面我们说过其实IO就是拷贝数据。 先说一下读取的接口&#xff1a; 当系统调用read/recv的时候会有两种情况 ①没有数据&a…

【C语言】指针进阶(3)

目录 指针和数组笔试题解析 一维数组 字符数组 二维数组 指针笔试题 在前面两篇文章&#xff0c;我们已经学完了指针进阶的所有知识点。在这篇文章中&#xff0c;我们主要学习的是一些常见的笔试题的总结。 指针和数组笔试题解析 在做题之前&#xff0c;我们先复习一下之…

第三讲:k8s核心概念和专业术语

序言&#xff1a;这里只对概念继续基础阐述&#xff0c;不做具体案例&#xff0c;这位博主写的特别详细&#xff0c;想要对k8s深入的了解可以跳转了&#xff0c;作为小白的我看的有点懵&#xff0c;毕竟没实践过 链接地址→ http://t.csdn.cn/ZYtEF 这篇文章写了将近两万字对各…

mybatis-plus 缓存深入实践(二)

mybatis-plus 缓存&#xff08;一&#xff09;回顾、缓存&#xff08;二&#xff09;深入实践

3D测量之圆柱轴线直线度测量

视频演示效果 圆柱轴线直线度测量 零、效果图 一、目标 测量圆柱轴线的直线度误差&#xff1b; 二、测量方法–轴截面法[1] 本文主要是通过最小二乘法确定各截面中心坐标值。由各截面测得的实际中心构成测得中心线。按误差评定方法进行数据处理&#xff0c;求出轴线的直线度误…

启动es容器错误

说明&#xff1a;启动es容器&#xff0c;刚启动就停止&#xff0c;查看日志&#xff0c;出现以下错误信息&#xff08;java.lang.IllegalArgumentException: Plugin [analysis-ik] was built for Elasticsearch version 8.8.2 but version 7.12.1 is running&#xff09; 解决&…