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

文章目录

    • 前言:
    • 一、 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.mfbz.cn/a/870064.html

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

相关文章

谷歌AI拿下IMO奥数银牌!6道题轻松解出4道~

本周四&#xff0c;谷歌DeepMind团队宣布了一项令人瞩目的成就&#xff1a;&#xff1a;用 AI 做出了今年国际数学奥林匹克竞赛 IMO 的真题&#xff0c;并且距拿金牌仅一步之遥。这一成绩不仅标志着人工智能在数学推理领域的重大突破&#xff0c;也引发了全球范围内的广泛关注和…

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法&#xff08;CPO&#xff09;优化VMD二次分解 目录 时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法&#xff08;CPO&#xff09;优化VMD二次分解效果一览基本介绍程序设计参考资料 效果一览…

leetcode-148. 排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5]示例 3&#x…

UFO:革新Windows操作系统交互的UI聚焦代理

人工智能咨询培训老师叶梓 转载标明出处 人机交互的便捷性和效率直接影响着我们的工作和生活质量。尽管现代操作系统如Windows提供了丰富的图形用户界面&#xff08;GUI&#xff09;&#xff0c;使得用户能够通过视觉和简单的点击操作来控制计算机&#xff0c;但随着应用程序功…

javaEE-04-Filter

文章目录 FilterFilter 的生命周期FilterConfig类FilterChain过滤器链Filter 的拦截路径 Filter Filter 过滤器它是 JavaWeb 的三大组件之一,它是 JavaEE 的规范。也就是接口,它的作用是&#xff1a;拦截请求&#xff0c;过滤响应。 Filter的工作流程图解&#xff1a; 以管…

HarmonyOS NEXT零基础入门到实战-第四部分

自定义组件: 概念: 由框架直接提供的称为 系统组件&#xff0c; 由开发者定义的称为 自定义组件。 源代码&#xff1a; Component struct MyCom { build() { Column() { Text(我是一个自定义组件) } } } Component struct MyHeader { build() { Row(…

【北京迅为】《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…

神经网络拟合任何函数的数学原理

神经网络拟合任何函数的数学原理 神经网络拟合能力的数学表达 神经网络之所以理论上可以拟合任何函数&#xff0c;其核心在于其多层的结构和非线性的激活函数。通过增加层数和神经元数量&#xff0c;神经网络可以逼近复杂的函数关系。这一过程可以通过万能近似定理&#xff08…

Vue中的diff算法

文章目录 diff算法是什么比较方式源码分析patchpatchVnodeupdateChildren小结Vue3中diff算法优化diff算法是什么 diff算法是一种通过同层的树节点进行比较的高效算法 其有两个特点: 比较只会在同层级进行,不会跨层级比较在dff比较的过程中,循环从两边向中间比较(首位交叉…

24年第三届钉钉杯大学生大数据挑战赛浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; 本次钉钉杯大数据挑战赛的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xf…

LiRouter V3.0无人机自主精细化巡检 LiStation V3.0输电线路巡检数障处理分系统 软件下载License使用

PeacePower LiRouter 输电线路无人机自主巡检航线规划系统&#xff08;本文档中简称 “LiRouter”&#xff09;&#xff0c;是基于高精度三维点云数据&#xff0c;在少量人工干预下为输电线路无人 机自主精细化巡检自动生成并输出航线的专业软件工具。 凭借在输电线路无人机智能…

04-数据库MySQL

一、项目要求 二、项目过程介绍 1、新建数据库 2、新建表 3、处理表 1.修改student 表中年龄(sage)字段属性&#xff0c;数据类型由int 改变为smallint 2.为Course表中Cno 课程号字段设置索引,并查看索引 3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引&#xf…

Vue使用FullCalendar实现日历/周历/月历

Vue使用FullCalendar实现日历/周历/月历 需求背景&#xff1a;项目上遇到新需求&#xff0c;要求实现工单以日/周/月历形式展示。而且要求不同工单根据状态显示不同颜色&#xff0c;一个工单内部&#xff0c;需要以不同颜色显示三个阶段。 效果图 日历 周历 月历 安装插件…

【分布式锁】Redission实现分布式锁

接着上一节&#xff0c;我们遇到了超卖的问题&#xff0c;并通过Redis实现分布式锁&#xff0c;进行了解决。本节 我将换一种方式实现分布式锁。 前提&#xff1a; nginx、redis、nacos 模块1&#xff1a; provider-and-consumer 端口 8023 模块2 rabbitmq-consumer 端口 8021 …

推荐几款支持AI剪辑并可使用个人视频素材的软件!

最强AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量 其实现在大部分的AI视频剪辑工具都可以实现一键成片&#xff0c;这里给你分享6款可以使用自己的素材实现AI剪辑的工具及其操作方法&#xff01; 一、剪映 剪映…

微信小程序之计算器

在日常生活中&#xff0c;计算器是人们广泛使用的工具&#xff0c;可以帮助我们快速且方便地计算金额、成本、利润等。下面将会讲解如何开发一个“计算器”微信小程序。 一、开发思路 1、界面和功能 “计算器”微信小程序的页面效果如图所示 在计算器中可以进行整数和小数的…

光猫设置桥接 路由器pppoe拨号 设置正常访问光猫 (openwrt)

网络信息展示 光猫桥接很简单吧&#xff0c;就不说了。先来列出修改前的网络接口和网络信息。 光猫192.168.1.1&#xff0c;openwrt 10.0.0.0/8 初始配置 需要记录的信息&#xff1a;WAN的网络设备&#xff08;eth1&#xff09;&#xff0c;光猫的IP&#xff08;192.168.1.1&am…

Qt中在pro中实现一些宏定义

在pro文件中利用 DEFINES 定义一些宏定义供工程整体使用。&#xff08;和在cpp/h文件文件中定义使用有点类似&#xff09;可以利用pro的中的宏定义实现一些全局的判断 pro中实现 #自定义一个变量 DEFINES "PI\"3.1415926\"" #自定义宏 DEFINES "T…

模拟电子技术-实验四 二极管电路仿真

实验四 二极管电路仿真 一&#xff0e;实验类型 验证性实验 二&#xff0e;实验目的 1、验证二极管的单向导电性 2、验证二极管的稳压特性。 三&#xff0e;实验原理 二极管的单向导电性&#xff1a; 四、实验内容 1、二极管参数测试仿真实验 1&#xff09;仪表仿真…

【MetaGPT系列】【MetaGPT完全实践宝典——多智能体实践】

目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT2-1、安装&配置2-2、使用已有的Agent&#xff08;ProductManager&#xff09;2-3、多智能体系统介绍2-4、多智能体案例分析2-4-1、构建智能体团队2-4-2、动作/行为 定义2-4-3、角色/智…