Vue3中 响应式 API ( readonly、shallowReadonly、toRaw、markRaw ) 详解

news2025/3/12 17:19:07

传送门:Vue3中 响应式 API ( reactive、ref、toRef、toRefs ) 详解
传送门:Vue3中 响应式 API( shallowReactive、shallowRef、triggerRef 、customRef )详解

1. readonly 函数

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。
只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。
要避免深层级的转换行为,请使用 shallowReadonly() 作替代。

<template>
  <div>
    <div>
      {{count}}
      <button @click="changeCount">changeCount</button>
    </div>
    <div>
      {{obj1.name}} {{obj1.info.age}}
      <button @click="obj1Age">obj1Age</button>
    </div>
  </div>
</template>

<script>
import { reactive,readonly, ref } from 'vue';
export default {
  setup(){
    let count = ref(0);
    let obj1 = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    count = readonly(count);
    obj1 = readonly(obj1);

    const changeCount = () => {
      count.value++;
      console.log(count)
    }
    const obj1Age = () => {
      obj1.name = '李四';
      obj1.info.age++;
      console.log(obj1)
    }
    return {
      count,
      changeCount,
      obj1,
      obj1Age,
    }
  } 
}
</script>

分别触发 changeCount、obj1Age 一次

在这里插入图片描述

2. shallowReadonly 函数

readonly() 的浅层作用形式
和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
在这里插入图片描述

<template>
  <div>
    <div>
      {{count}}
      <button @click="changeCount">changeCount</button>
    </div>
    <div>
      {{obj1.name}} {{obj1.info.age}}
      <button @click="obj1Age">obj1Age</button>
    </div>
  </div>
</template>

<script>
import { reactive,shallowReadonly, ref } from 'vue';
export default {
  setup(){
    let count = ref(0);
    let obj1 = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    count = shallowReadonly(count);
    obj1 = shallowReadonly(obj1);

    const changeCount = () => {
      count.value++;
      console.log(count)
    }
    const obj1Age = () => {
      obj1.name = '李四';
      obj1.info.age++;
      console.log(obj1)
    }
    return {
      count,
      changeCount,
      obj1,
      obj1Age,
    }
  } 
}
</script>

分别触发 changeCount、obj1Age 一次

在这里插入图片描述

3. toRaw 函数

根据一个 Vue 创建的代理返回其原始对象。
toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。
这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

<template>
  <div>
    <div>
      {{obj.name}} {{obj.info.age}}
      <button @click="objToRaw">objToRaw</button>
    </div>
  </div>
</template>

<script>
import { reactive,toRaw } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    const objToRaw = () => {
      let objRaw = toRaw(obj)
      objRaw.info.age++
      console.log(obj,objRaw)
    }
    return {
      obj,
      objToRaw,
    }
  } 
}
</script>

触发 objToRaw 两次
在这里插入图片描述

4. markRaw 函数

将一个对象标记为不可被转为代理。返回该对象本身。
作用:标记一个对象,使其永远不会再成为响应式对象;
应用场景:

  • 有些值不应被设置为响应式的,如:复杂的第三方类库等;
  • 当渲染具有不可变数据源的大列表时,跳过响应式转换可提高性能;

在这里插入图片描述

<template>
  <div>
    <div>姓名:{{obj.name}} </div> 
    <div>年龄:{{obj.info.age}} </div> 
    <div v-if="obj.car">座驾:{{obj.car}} </div> 
    <div v-if="obj.address">地址:{{obj.address}} </div> 
    <button @click="updateObj">updateObj</button>
    <button @click="changeAddress">changeAddress</button>
    <button @click="changeCar">changeCar</button>
  </div>
</template>

<script>
import { reactive,markRaw } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    const updateObj = () => {
      const address = { province:'湖北',city:'武汉' };
      obj.address = address; // obj 配置了 Proxy 代理,因此捕获到对 obj 任何属性的操作且都是响应式的;
      const car = { brand:'宝马',price:30 };
      obj.car = markRaw(car); // car内部属性值已经改了,只是没有响应式更新。它和readonly不同,readonly是压根不让修改 
    }

    function changeAddress(){
      obj.address.province = '江苏';
      obj.address.city = '南京';
      console.log(obj) 
    }
    
    function changeCar(){
      obj.car.brand = 'BMW',
      obj.car.price+= 1
      console.log(obj)
    };

    return {
      obj,
      updateObj,
      changeCar,
      changeAddress,
    }
  } 
}
</script>

依次触发 updateObj、changeAddress、changeCar 一次,效果如下:
(若先触发 changeCar 再触发 changeAddress ,car 的页面信息会进行更新,因为 address 的改变带动了页面的更新 )
在这里插入图片描述

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

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

相关文章

深度学习visio作图技巧

目录 1.不显示跨线 2.调节连接线拐弯 3.方框与连接线反应 4.设计一个卷积块/特征图 5.设计一个特征图方块 1.不显示跨线 不显示跨线&#xff1a;设计→连接线&#xff0c;取消显示 跨线的勾选 2.调节连接线拐弯 连接线拐弯&#xff1a;按住shift拖动线条即可控制连接线拐…

高数(下) 第十二章:无穷级数

文章目录Ch12. 无穷级数(一) 常数项级数正项级数交错级数任意项级数4个特殊的常数项级数收敛级数的性质&#xff08;针对任意项级数&#xff09;常数项级数的审敛法1.正项级数审敛法(判别法)(1)比较判别法(2)比较审敛法极限形式(3)比值法(4)根值法(5)收敛的充要条件(6)绝对收敛…

Spring Boot 篇四: Spring Data JPA使用SQL Server

本文目录SQL Server Express的安装或直接DockerSQL Server JDBC DriverTCP/IP 链接端口Integrated SecuritySSL总结本篇介绍篇一至篇三中用到的JPA链接SQL Server的具体情况以及实战过程中可能遇到的问题。 SQL Server Express的安装或直接Docker 具体的下载和安装教程&#…

sanic:通过dockerfile部署

简介&#xff1a;长期以来&#xff0c;环境一直是部署的难题。如果您的项目中有冲突的配置&#xff0c;您将不得不花费大量时间来解决它们。幸运的是&#xff0c;虚拟化为我们提供了一个很好的解决思路。Docker 就是其中之一。 历史攻略&#xff1a; sanic框架&#xff1a;简…

内网渗透体系学习1

工作组 工作组(Work Group)是计算机网络的一个概念&#xff0c;也是最常见和最普通的资源管理 模式&#xff0c;就是将不同的计算机按照功能或部门分别置于不同的组。通过创建不同的 工作组&#xff0c;不同的计算机可以按照功能或部门归属到不同的组内&#xff0c;整个组织的网…

XSCTF联合招新赛-热身赛(部分WP)

由于没有多少时间答题,抽空在划水的时候做了一两道题目.比赛已经结束了24小时了。特把写的WP分享一下,欢迎各位大佬进行指点。 文章目录warm_up头头是道B45364EZphpeasy_sqlbaigeiRSAimage1image2image3image42^11warm_up 只有虔诚的嘉心糖才能成功拿到flag 地址&#xff1a;4…

5G核心网技术基础自学系列 | 语音业务

书籍来源&#xff1a;《5G核心网 赋能数字化时代》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G核心网技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 3.9.1 5G语音概述 除了用于机器之…

libusb系列-003-Linux下libusb源码编译

libusb系列-003-Linux下libusb源码编译 文章目录libusb系列-003-Linux下libusb源码编译摘要源码下载及解压下载源码解压下载的源码压缩包打开终端准备编译环境安装make dh-autoreconf安装 libudev-dev编译错误的教程增加执行bootstrap.sh指令再编译make安装库确认下关键字&…

C语言中的文件操作那些事儿~~

是时候该学着操作文件了什么是文件文件种类文件名为什么要使用文件文件的打开和关闭文件的顺序读写fgetc/fputcfgets/gputsfscanf/fprintffread/fwrite文件的随机读写fseekftellrewind文件读取结束的判断文件缓冲区男人过了二十岁就要学着沉稳&#xff0c;遇到问题不要慌&#…

【Java】异常

看似不起波澜的日复一日 会突然在某一天让人看到坚持的意义 目录 1.认识异常 1.1 异常的概念 1.2 常见的异常 2.异常的体系结构 3.异常的分类 3.1 编译时异常 3.2 运行时异常 4.异常的处理 4.1 事前防御型 4.2 事后认错型 5.事后认错型处理 5.1 异常的抛出…

第22章 软件安装 RPM/ YUM

上章节是用源代码来编译完成&#xff1b; 发商编译好之后直接把可执行文件发布给用户来安装也是一种方法&#xff0c;类似于windows下的安装&#xff1b; 客户端取得这个文件后&#xff0c;只要通过特定的指令来安装&#xff0c; 那么该软件文件就会依照内部的脚本来检测相依的…

C++数据结构之堆栈

主要参考资料:01.堆栈基础知识 | 算法通关手册 (itcharge.cn)01.堆栈基础知识 | 算法通关手册 (itcharge.cn) 本文主要采用C实现&#xff0c;而参考资料主要采用python实现&#xff0c;可以相互结合食用。 基础知识 定义 堆栈&#xff08;Stack&#xff09;&#xff1a;简称为…

MySQL数据库学习(4)

DQL分组查询 语法&#xff1a; SELECT 字段列表 FROM 表名[ WHERE条件 ] GROUP BY 分组字段名 [HAVING分组后过滤条件]; 我们发现分组查询中有两个条件&#xff0c;这两个条件的区别是什么呢&#xff1f;执行时机不同: where是分组之前进行过滤&#xff0c;不满足where条件&a…

基于SSM的疫情管控系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

大数据Hadoop之——Apache Hudi 数据湖实战操作(Spark,Flink与Hudi整合)

文章目录一、概述二、Hudi CLI三、Spark 与 Hudi 整合使用1&#xff09;Spark 测试2&#xff09;Spark 与 Hudi 整合使用1、启动spark-shell2、导入park及Hudi相关包3、定义变量4、模拟生成Trip乘车数据5、将模拟数据List转换为DataFrame数据集6、将数据写入到hudi四、Flink 与…

前端ES6相关的面试题

前端ES6相关的面试题 文章目录前端ES6相关的面试题一. var let constvarletconst二 . 函数的扩展reset参数箭头函数三 . 数组的扩展四.Set和map数据结构Setmap五. Promise六. 模块化一. var let const var var存在声明提升 >先上车,后买票 var声明的变量会挂载到window下面…

Java实操避坑指南四、spring中的坑

文章目录1. 项目搭建过程1. pom 依赖2. 在没有配置数据库相关时不要引入依赖包&#xff0c;如spring-boot-starter-data-jpa2. spring bean 默认生成策略的正确使用1. 代码示例2. 单元测试3. 工具类 [参考](#test2)4. 报错信息5. 分析6. 使用说明2. 使用了Autowired 注解&#…

【5G RAN】5G gNB间的N2/NGAP切换(handover)那点事儿

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

@Import注解详解

Import这个注解非常重要&#xff0c;而且在springboot项目当中随处可见&#xff0c;就拿springboot启动类来说&#xff0c;我们经常会遇到一些Enable相关的注解&#xff0c;例如开启异步EnableAsync、开启缓存支持EnableCaching、开启定时任务EnableScheduling等等… 目录一、I…

Oracle通过DBLINK访问达梦数据库

环境需求 需要安装配置以下相关软件&#xff1a; 1、Oracle Gateways 2、ODBC数据源&#xff08;gateway机器&#xff09; 3、达梦数据库软件&#xff08;gateway机器&#xff09; 安装配置 Windows环境 安装达梦数据库软件 安装步骤省略&#xff0c;可以参考DM 数据库…