当前位置: 首页 > news >正文

揭开 Vue 3 中大量使用 ref 的隐藏危机

在 Vue 3 中,ref 是用来创建响应式的引用,它能够追踪和管理单一的变量或对象。当代码中大量使用 ref 时,虽然可以实现对各个状态或数据的精细控制,但也会带来一些问题和潜在影响。

1. 大量使用 ref 带来的问题

1、代码冗长与维护成本高

当一个组件中大量使用 ref,每个状态都需要单独的声明和赋值,会导致代码变得冗长、不易阅读。而且会频繁看到 ref(变量)和 变量.value 的形式,这使得代码的可读性降低,维护变得更加困难。

2、响应式系统性能负担

每个 ref 创建的响应式对象都要被 Vue 的响应式系统追踪和更新。当存在大量的 ref ,Vue 的响应式系统需要处理更多的状态变化,可能会对性能产生负面影响,特别是在大型应用或复杂组件中。

3、频繁 .value 操作

ref 包装的值需要通过 .value 来访问或更新,这在某些情况下容易引发不必要的重复代码,降低代码的简洁性。此外,使用时还需特别注意,什么时候该使用 .value,什么时候不使用。

4、数据管理混乱

当一个组件中有太多 ref,会导致管理状态变得复杂,难以明确哪个 ref 控制哪个部分的数据或逻辑,增加了组件的复杂度。

2. 改进方法

2.1 使用 reactive 替代 ref

如果需要管理多个相关的状态,建议使用 reactive 而不是多个 ref。reactive 可以将整个对象变成响应式的,这样就可以操作对象的属性来管理多个状态,而不需要单独创建多个 ref。

举个 🌰

1、使用 ref

<template><div class="container"><p>name:{{ name }}</p><p>age:{{ age }}</p><p>address:{{ address }}</p></div>
</template><script>
import { ref } from 'vue';
export default {setup() {const name = ref('');const age = ref(0);const address = ref('');const createUser = () => {name.value = 'John';age.value = 20;address.value = 'New York';};createUser();return {name,age,address,};},
};
</script>

2、优化后使用 reactive 

<template><div class="container"><p>name:{{ user.name }}</p><p>age:{{ user.age }}</p><p>address:{{ user.address }}</p></div>
</template><script>
import { reactive } from 'vue';
export default {setup() {const user = reactive({name: '',age: 0,address: '',});const createUser = () => {user.name = 'John';user.age = 20;user.address = 'New York';};createUser();return {user,};},
};
</script>

展示都是一样的:

在这个例子中,使用 reactive 将 name、age 和 address 放在同一个对象中管理,减少了多个 ref,使代码更加简洁,且更容易维护。

2.2 使用 computed 来处理派生状态

如果某个状态是从其他状态推导出来的,那么可以使用 computed 来代替 ref,从而避免创建额外的响应式数据。

举个 🌰

import { ref, computed } from 'vue';export default {setup() {const firstName = ref('John');const lastName = ref('Doe');// 使用 computed 来合成新的状态,而不是通过 ref 手动管理const fullName = computed(() => `${firstName.value} ${lastName.value}`);return {firstName,lastName,fullName,};},
};
2.3 使用组合式函数 (Composables)

当状态逻辑非常复杂时,考虑将逻辑拆分成多个组合式函数(Composables)。这不仅有助于代码组织,还能在不同组件间共享相似的逻辑,而不是在每个组件中重复定义多个 ref。

举个 🌰

<template><div class="container"><p>name:{{ user.name }}</p><p>age:{{ user.age }}</p><p>address:{{ user.address }}</p></div>
</template><script>
import { ref, reactive } from 'vue';
// 组合式函数:管理用户信息
function useUser() {const user = reactive({name: '',age: 0,address: '',});const updateUser = (newUser) => {user.name = newUser.name;user.age = newUser.age;user.address = newUser.address;};return {user,updateUser,};
}
export default {setup() {const { user, updateUser } = useUser();updateUser({name: 'Monica',age: 18,address: 'China',});return {user,};},
};
</script>

展示为:

这样可以将复杂的逻辑拆分到组合式函数中,在不同组件间复用状态和方法,减少了组件内部的状态管理复杂度。

3. 注意事项

1、ref vs reactive 区别

虽然 ref 和 reactive 都可以实现响应式状态管理,但 ref 适合处理单一原始值(如数字、字符串等),而 reactive 适合处理对象。为了避免不必要的复杂性,当有多个相关状态时优先使用 reactive。

2、.value` 的使用

ref 的 .value 访问方式在 Vue 3 是强制的(除非使用解构 toRefs 等)。频繁使用 .value 会显得繁琐,所以如果要管理多个属性,最好使用 reactive 来避免这些问题。

3、watch 和 ref 

当使用 watch 监听 ref 时,注意 .value 的引用变化。Vue 的 watch 默认是深度监听(deep),在处理复杂对象时可以通过配置 deep: false 来避免不必要的性能开销。

总结:

使用大量 ref 可能导致代码冗长、性能问题和维护难度的增加。为了解决这些问题,可以采用 reactive 管理多个状态,使用 computed 来处理派生状态,或者使用组合式函数来拆分逻辑。通过优化 ref 的使用,可以提升代码的可读性、性能和易维护性。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CentOS 7官方源停服,配置本机光盘yum源
  • super-this详解
  • 1.2 测试基础
  • 【.NET全栈】ASP.NET实战—基于ASP.NET的求职系统设计与实现
  • code eintegrity npm err sha512
  • 算法笔试-编程练习-好题-06
  • MyBatis系统学习(三)——动态SQL
  • 数仓项目环境搭建
  • 828华为云征文 | 云服务器Flexus X实例,搭建上线前后端项目
  • 电脑桌面如何分区展示工作任务?
  • 唯品会大数据面试题及参考答案(3万字长文)
  • Qt与Udp
  • 力扣最热一百题——合并两个有序链表
  • 运维工程师面试整理-安全常见安全漏洞及修复
  • 【RabbitMQ 项目】服务端:数据管理模块之虚拟机模块
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • MD5加密原理解析及OC版原理实现
  • Next.js之基础概念(二)
  • Python中eval与exec的使用及区别
  • SQL 难点解决:记录的引用
  • 好的网址,关于.net 4.0 ,vs 2010
  • 回顾 Swift 多平台移植进度 #2
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 解析带emoji和链接的聊天系统消息
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 三分钟教你同步 Visual Studio Code 设置
  • 我的zsh配置, 2019最新方案
  • 协程
  • 新书推荐|Windows黑客编程技术详解
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​虚拟化系列介绍(十)
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #Linux(Source Insight安装及工程建立)
  • (¥1011)-(一千零一拾一元整)输出
  • (1)Hilt的基本概念和使用
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (33)STM32——485实验笔记
  • (52)只出现一次的数字III
  • (Matlab)使用竞争神经网络实现数据聚类
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (八)Flink Join 连接
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (六)vue-router+UI组件库
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (一)SpringBoot3---尚硅谷总结
  • (一)基于IDEA的JAVA基础12
  • (转)memcache、redis缓存
  • (转)VC++中ondraw在什么时候调用的
  • (转载)Google Chrome调试JS