vue3响应式用法(高阶性能优化)

news2024/9/23 11:26:47

文章目录

    • 前言:
    • 一、 shallowRef()
    • 二、 triggerRef()
    • 三、 customRef()
    • 四、 shallowReactive()
    • 五、 toRaw()
    • 六、 markRaw()
    • 七、 shallowReadonly()
    • 小结:

在这里插入图片描述

前言:

翻别人代码时,总结发现极大部分使用vue3的人只会用refreactive处理响应式数据无论什么场景都是,但vue官方针对某些应用场景有其它的更好用的响应式api实现响应式,从而达到更好的性能效果。例如深层的树状数据结构可以通过shallowRef实现浅层响应式,不会被深层递归地转为响应式。本文通过例子详细总结几种vue3响应式的高阶用法。

一、 shallowRef()

简述:ref的浅层作用形式。shallowRef与普通的 ref 的区别在于,shallowRef 不会对对象进行深度的响应式处理,也就是 shallowRef 包含的对象内部的属性发生变化时,shallowRef 本身不会触发重新渲染或响应式更新,所以使用shallowRef时只关心顶层的引用变化。

代码示例:

<script lang="ts" setup>
  import { shallowRef } from 'vue';

  const data = shallowRef({ name: '天天鸭', age: 18 });

  // 修改顶层引用会触发响应式更新
  data.value = { name: 'Bob', age: 20 };

  // 修改内部属性不会触发响应式更新
  data.value.age = 30;
</script>

作为性能优化的一种手段,当业务场景中有大量复杂数据结构但只有顶层引用需要响应式时就非常有用,但你需要更加注意对象的更新逻辑,确保在需要时正确地应用响应式转换。

二、 triggerRef()

简述:用于强制执行依赖于 shallowRef 的副作用。也就是说当使用shallowRef响应式时只能修改顶层数据,但特殊情况使用 triggerRef可以强制修改内层属性,大大提高灵活性。

代码示例:

<script lang="ts" setup>
  import { shallowRef, triggerRef } from 'vue';

  const data = shallowRef({ name: '天天鸭', age: 18 });

  // 修改内部属性不会触发响应式更新
  data.value.age = 30;

  // 但这里调用 triggerRef 强制更新
  triggerRef(data);
</script>

triggerRef 一般配合shallowRef一起使用,起到提高shallowRef的灵活性的同时又能优化性能的效果。需要注意执行顺序确保在修改了 shallowRef 内部对象的属性之后才调用。

三、 customRef()

简述:customRef 功能非常之强大,customRef可以创建自定义的 ref 对象,这些对象可以有更复杂的依赖跟踪和依赖更新逻辑。具体是customRef 接收一个工厂函数,该函数必须要返回一个具有 getset 方法的对象。这些方法用于读取和修改引用值,并且通过getset里面的逻辑可以显式地控制依赖关系的跟踪和响应式更新。

代码示例: 实现一个有防抖功能的ref,第9和17行的track()trigger()是固定写法,这是vue3底层响应式原理相关的,这里就不多解释了。

<script lang="ts" setup>
import { customRef } from 'vue';

function debouncedRef(initialValue, delay) {
  let timeoutId;
  return customRef((track, trigger) => ({
  
    get() {
      // 使用 track 函数标记依赖
      track();
      return initialValue;
    },
    
    set(newValue) {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        initialValue = newValue;
        // 使用 trigger 函数触发依赖更新
        trigger();
      }, delay);
    }
    
  }));
}

// 使用自定义的ref
const myDebouncedRef = debouncedRef('Hello Word', 500);
</script>

在上述例子中,debouncedRef 是一个自定义的 ref 工厂函数,它接收两个参数分别是初始值和延迟时间。当 set 方法被调用时,会清除之前的计时器并设置一个新的计时器,在延迟时间结束后更新值并触发依赖更新。

在组件中使用:

<script lang="ts" setup>
import { onMounted } from 'vue';
import { debouncedRef } from './debouncedRef';

export default {
  setup() {
    const myDebouncedRef = debouncedRef('Hello Word', 500);

    onMounted(() => {
      // 在组件挂载后,可以通过 .value 访问 ref 的值
      console.log(myDebouncedRef.value);  // 时间到之后返回 'Hello Word'
    });
  },
};
</script>

注意: customRef 返回的对象必须有一个 value 属性用于访问或修改引用的值,这是 vue 规定的。除此以外customRef能根据业务需求实现各种定制化的ref, 如异步更新、条件性更新、防抖、节流等

四、 shallowReactive()

简述:reactive的浅层作用形式, 和shallowRef的功能比较类似。shallowReactive与普通的 reactive 的区别在于,shallowReactive 不会对对象进行深度的响应式处理,也就是 shallowReactive 包含的对象内部的属性发生变化时,shallowReactive 本身不会触发重新渲染或响应式更新,所以使用shallowReactive时只关心顶层的引用变化。

代码示例:

<script lang="ts" setup>
  import { shallowReactive, isReactive } from 'vue';
  const statetest = shallowReactive({
    foo: 1,
    nested: {
      age: 18,
    },
  });

  statetest.foo++;    // 更改状态自身的属性是响应式的

  // 下层嵌套对象不会被转为响应式
  isReactive(statetest.nested); // false

  statetest.nested.age++;     // 不是响应式的
</script>

作为性能优化的一种手段,当业务场景中有大量复杂数据结构但只有顶层引用需要响应式时就非常有用,但你需要更加注意对象的更新逻辑,确保在需要时正确地应用响应式转换。

五、 toRaw()

简述:toRaw用于获取 reactiveref 创建的响应式代理对象的原始值。当我们使用 reactiveref 创建一个对象或值时,Vue 会在内部创建一个代理对象,这个代理对象能够追踪属性的变化并触发视图的更新。但有时候需要访问这个对象的非响应式版本时toRaw 就派上用场了。

代码示例:

<script lang="ts" setup>
  import { reactive, toRaw } from 'vue';

  const state = reactive({ count: 0 });

  // 获取响应式转为原始对象
  const rawState = toRaw(state);

  // 修改原始对象不会触发响应式更新
  rawState.count = 10;
  // 仍然输出 0,因为 state 是响应式代理,未被修改
  console.log(state.count); 
</script>

使用 toRaw 获取的原始对象将不再具有响应性。即toRaw 提供了一种方式来绕过 Vue 的响应式系统,这对于性能优化和处理外部库至关重要。当正在处理一个大的数据结构,并且知道某些操作不会导致 UI 更新时使用特别合适。

六、 markRaw()

简述:作用是标记一个对象,使其不再被 reactiveshallowReactive 转换为响应式代理。即你之后试图用这些函数包装这个对象,它也会保持原样,不会变成响应式的。

代码示例: markRaw 主要用于标记对象,而不是基本类型的值

<script lang="ts" setup>
  import { markRaw } from 'vue';

  const someObject = { name: '天天鸭' };
  const markedObject = markRaw(someObject);

  // 即使使用 reactive,markedObject 也不会变成响应式
  const state = reactive({ obj: markedObject });
</script>

注意: markRaw不适用于ref,因为ref 的工作方式与 reactive 有点区别。ref 主要用于创建一个响应式引用,它可以封装任何类型的值如字符串、数字和对象。当你创建一个 ref 时,Vue 并不是将整个对象转换为响应式代理,而是将 ref 本身作为一个响应式引用,通过 value 属性来访问和修改其内部的值。

因此,当你将一个对象放入 ref 时,ref 本身依然是响应式的,而 markRaw 的作用是阻止对象被转换为响应式,这和 ref 的设计并不匹配。

七、 shallowReadonly()

简述:readonly 的浅层作用形式。和 readonly 类似,shallowReadonly 会把对象的属性变为只读,但是它只会影响到对象的顶层属性,而不会递归地使对象内部的属性也变为只读。

代码示例:

<script lang="ts" setup>
import { shallowReadonly } from 'vue';

const state = {
  name: '天天鸭',
  profile: {
    age: 18,
    address: {
      city: '广州',
    }
  }
};
const shallowState = shallowReadonly(state);

// 这将会抛出错误,因为顶层属性是只读的
shallowState.name = 'change天天鸭';

// 这是可以的,因为 `profile` 对象没有被设为只读
shallowState.profile.age = 31; 

// 同样,`address` 对象也可以被修改
shallowState.profile.address.city = '深圳';
</script>

使用 shallowReadonly 的对象在顶层是只读的,但其内部的嵌套对象或数组仍然可以被修改。如果数据结构第一层业务需求不会改变就特别适用。

小结:

在真实做项目时其实不用这些进阶用法同样能实现功能,但是在合适的场景用上了却能锦上添花,作为一个有一定经验的vue程序员更是要必会了。如果我写的哪里不对或者不好欢迎大佬指出。

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

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

相关文章

废品回收小程序制作,数字化带来的商业机会

随着社会环保意识的增强&#xff0c;废品回收成为了一个热门行业&#xff0c;它不仅能够减少资源浪费&#xff0c;还能够带来新的商业机会&#xff01; 当下&#xff0c;废品回收小程序已经成为了回收市场的重要方式&#xff0c;为回收行业的发展注入新鲜活力&#xff0c;推动…

如何使用C#快速创建定时任务

原文链接&#xff1a;https://www.cnblogs.com/zhaotianff/p/17511040.html 使用Windows的计划任务功能可以创建定时任务。 使用schtasks.exe可以对计划任务进行管理&#xff0c;而不需要编写额外代码 这里掌握schtasks /CREATE 的几个核心参数就可以快速创建计划任务 /SC …

【短视频批量剪辑系统源代码开发部署技术分享】

多视频一键剪辑&#xff0c;创意无限升级 在确保音视频同步的基础之上&#xff0c;可视化剪辑技术再次迎来重大升级。最新引入的“多脚本升多视频”功能&#xff0c;标志着可视化剪辑矩阵的全面进步&#xff0c;为内容创作带来了前所未有的便利和灵活性。 这一功能的引入使得一…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十五章 Pinctrl和GPIO子系统实验

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

超声波眼镜清洗机有必要买吗?不踩坑的超声波眼镜清洗机选购攻略

超声波眼镜清洗机有必要买吗&#xff1f;当然有必要啦&#xff01;眼镜戴久&#xff0c;镜片难免会脏&#xff0c;镜片看起来会越来越模糊&#xff0c;不仅会影响清晰度还会影响美观&#xff0c;如果是经常戴妆出门的女生&#xff0c;镜托位置污垢也会越来越脏&#xff0c;有些…

windows下运行sh文件

1、打开git bash 2、进入sh文件所在文件夹&#xff0c;使用sh xx.sh运行

Python爬虫掌握-----4实战(爬取视频)

我们使用爬虫时难免会遇到爬取视频的情况&#xff0c;其实爬取图片视频&#xff0c;内容都是一样的。这里以b站视频为例。 一、开始 1.找到url&#xff0c;请求url 防盗链&#xff0c;需要写在UA伪装中 正常的三步&#xff1a; 1.url 2.requests请求 3.UA伪装 import req…

基于迁移学习的手势分类模型训练

1、基本原理介绍 这里介绍的单指模型迁移。一般我们训练模型时&#xff0c;往往会自定义一个模型类&#xff0c;这个类中定义了神经网络的结构&#xff0c;训练时将数据集输入&#xff0c;从0开始训练&#xff1b;而迁移学习中&#xff08;单指模型迁移策略&#xff09;&#x…

【性能优化】在大批量数据下使用 HTML+CSS实现走马灯,防止页面卡顿(二)

上一篇只是简单演示了’下一张’的操作和整体的设计思路,这两天把剩余功能补全了,代码经过精简,可封装当成轮播组件使用,详细如下. 代码 <template><div class"container"><button click"checkNext(last)">上一张</button><b…

C++之栈和队列使用及模拟实现

目录 栈的使用 队列的使用 栈的模拟实现 队列的模拟实现 deuqe容器介绍 在C语言中我们已经学习了栈和队列的相关性质&#xff0c;今天我们主要来学习C语法中栈和队列的相关概念。 栈的使用 在C中栈是一种容器适配器&#xff0c;在其内部适配了其它的容器&#xff0c;其相…

go程序在windows服务中优雅开启和关闭

本篇主要是讲述一个go程序&#xff0c;如何在windows服务中优雅开启和关闭&#xff0c;废话不多说&#xff0c;开搞&#xff01;&#xff01;&#xff01;   使用方式&#xff1a;go程序 net服务启动 Ⅰ 开篇不利 Windows go进程编译后&#xff0c;为一个.exe文件,直接执行即…

使用api 调试接口 ,配置 Header 、 body 远程调试 线上接口

学习目标&#xff1a; 目标 使用api 调试接口 &#xff0c;配置 Header 、 body 远程调试 线上接口 学习内容&#xff1a; 内容 设置请求方式 2. 选择 POST 提交 3.设置 Header 一般默认的 4个 header 属性就可以直接使用&#xff0c;如有特殊情况&#xff0c;需进行属性设…

Docusaurus VS VuePress:哪一个更适合你的技术文档?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

springcloud接入seata管理分布式事务

下载安装包 链接: seata 配置seata-server 文件上传Linux解压 压缩包我放在/usr/local/seata中 tar -zxvf seata-server-2.0.0.tar.gz修改配置文件 设置nacos为注册和配置中心 进入文件夹 cd /usr/local/seata/seata/conf修改application.yml文件 ...... ...... cons…

关键词查找【Aho-Corasick 算法】

【全程干货】程序员必备算法&#xff01;AC自动机算法敏感词匹配算法&#xff01;动画演示讲解&#xff0c;看完轻松掌握&#xff0c;面试官都被你唬住&#xff01;&#xff01;_哔哩哔哩_bilibili 著名的多模匹配算法 引入依赖&#xff1a; <dependency><groupId>…

ICMPv6与DHCPv6之网络工程师软考中级

ICMPv6概述 ICMPv6是IPv6的基础协议之一。 在IPv6报文头部中&#xff0c;Next Header字段值为58则对应为ICMPv6报文。 ICMPv6报文用于通告相关信息或错误。 ICMPv6报文被广泛应用于其它协议中&#xff0c;包括NDP、Path MTU发现机制等 ICMPv6控制着IPv6中的地址自动配置、地址…

前端知识--前端访问后端技术Ajax及框架Axios

一、异步数据请求技术----Ajax Ajax是前端访问后端的技术&#xff0c;为异步请求&#xff08;不刷新页面&#xff0c;请求数据&#xff0c;只更新局部数据&#xff09;。 例如&#xff1a;在京东网站中搜索电脑&#xff0c;就会出现一些联想搜索&#xff0c;但此时页面并没有…

AI行业合适做必应bing推广吗?怎么开户呢?

快速发展的AI行业中&#xff0c;有效的市场获客渠道是关键&#xff0c;随着数字营销领域的不断演进&#xff0c;必应Bing以其独特的市场定位、庞大的用户基础和高效的广告系统&#xff0c;成为AI企业推广策略中的重要一环。特别是针对那些寻求精准触达、高效转化的AI企业而言&a…

2024国际燃气轮机运维周线上分享第一期开启!共探燃机新生态

为促进国内重型燃气轮机运维技术发展&#xff0c;加快建立独立自主的燃气轮机运维技术体系&#xff0c;2024国际燃气轮机运维大会将于2024年10月17-18日在中国广州盛大召开&#xff01; 2024国际燃气轮机运维大会将通过线上直播会议、线下技术分享及颁奖典礼等形式展开&#xf…

血泪史!ora-00600 16305报错解决过程

一个客户重启操作系统后数据库启动不了,检查日志发现报错ORA-00600 [16305] 在MOS中找了一下,发现说是loopback地址不通: 测试了一下ping 127.0.0.1不通. 再次多次尝试发现登录到服务器上面,在本机上ping 127 localhost 本机实际地址 都不通,但是其它服务器可以ping通他的…