vue3中ref和reactive的用法,区别和优缺点,以及使用场景

server/2024/10/25 12:42:01/

写在前头:
reactive定义的数据只能修改里面的属性,不能将整个数据替换,实在要替换请使用
 

			Object.assign(obj1, obj2);

举个例子
这种写法无法直接改变obj1

let obj1 = reactive({name: '猫',age: '2',
});obj1 = {name: '猪',age: '2',
}

正确的写法
 

let obj1 = reactive({name: '猫',age: '2',
});
Object.assign(obj1, {name: '猪',age: '2',});

或者逐个更改属性
 

let obj1 = reactive({name: '猫',age: '2',
});
obj1.name = '狗'obj1.age = '3'

言归正传:

Vue 3 中,refreactive 是管理响应式数据的两种主要方式。它们的使用场景、工作原理以及各自的优缺点有所不同。以下是它们的用法、区别、优缺点及推荐使用场景的总结。

1. ref 用法

ref 用于定义基本类型或复杂类型的响应式数据。它适合处理基本数据类型(如数字、字符串、布尔值),也可用于对象和数组。

用法示例
import { ref } from 'vue';export default {setup() {const count = ref(0); // 基本数据类型const name = ref('Vue3'); // 字符串const user = ref({ name: 'Alice', age: 25 }); // 对象const increment = () => {count.value++;  // 通过 .value 访问或修改 ref 包裹的值};return { count, name, user, increment };}
};
优点
  • 适合基本数据类型:对于简单的数据类型(如数字、字符串、布尔值),ref 是最佳选择。
  • 可以封装任何类型的数据:不仅限于基本类型,还可以封装对象、数组等复杂类型。
  • 引用式包装:即便是对象或数组,在使用 .value 时也能获取和修改它们的内容。
缺点
  • 需要通过 .value 访问:必须通过 ref.value 的形式访问和更新数据,初学者有时容易忘记或感到不便。
使用场景
  • 简单的原始数据类型:数字、字符串、布尔值等。
  • 需要手动包装非响应式对象:比如希望将一个对象显式地封装为响应式对象。
  • HTML元素引用:通过 ref 还能获取 DOM 元素的引用,比如在模板中操作具体的 DOM。

2. reactive 用法

reactive 用于将对象或数组转换为响应式数据。它适合处理复杂数据结构(如对象、数组等)。

用法示例
import { reactive } from 'vue';export default {setup() {const user = reactive({name: 'Alice',age: 25,hobbies: ['reading', 'coding']});const incrementAge = () => {user.age++;  // 直接修改对象属性,无需 .value};return { user, incrementAge };}
};
优点
  • 直观的语法:不需要 .value,可以像操作普通对象一样直接访问和修改属性,写法更加简洁。
  • 深度响应式reactive 会对对象的所有嵌套属性进行深度监听,无需手动处理嵌套数据。
缺点
  • 只能用于对象和数组reactive 不能用于基本数据类型,如数字、字符串等。
  • 不能直接解构reactive 对象不能直接解构,否则解构后的属性将失去响应式能力。
使用场景
  • 复杂的数据结构:适合对对象、数组、嵌套数据进行响应式管理。
  • 更符合面向对象的数据组织:需要管理对象之间的层级和属性关系时,reactive 更加自然。

3. refreactive 的区别

特性refreactive
适用场景基本数据类型、DOM引用、复杂类型封装对象、数组、嵌套数据
访问方式必须通过 .value 来访问和修改值直接通过对象属性访问和修改
响应式行为对于对象或数组,只有包裹的整体是响应式的,内部属性需要手动用 ref深度响应式,对所有嵌套属性进行监听
能否解构ref 可以解构(解构后仍然需 .value解构后失去响应式能力
语法简洁性访问属性时需要使用 .value操作对象时无需额外 .value

4. 优缺点对比

ref 的优缺点
  • 优点
    • 可以用于任何类型(基本数据类型、对象、数组)。
    • DOM 元素引用方便,常用于操作 template 中的元素。
  • 缺点
    • 必须使用 .value 访问和修改数据,稍显冗余。
    • 对于复杂对象或数组,只能将其整体变为响应式,内部属性需要手动处理。
      具体解释:

      在 Vue 3 中,ref 可以将基本数据类型(如数字、字符串)以及复杂类型(如对象、数组)变为响应式。但当我们使用 ref 包装复杂对象或数组时,ref 只能将整个对象或数组视为一个整体变为响应式,如果你需要对该对象的内部属性进行精细的响应式处理,可能需要手动处理内部属性的响应式特性。

      ref 对复杂对象或数组的处理

      当你用 ref 来处理复杂对象(如对象、数组)时,虽然这个复杂对象是响应式的,但在修改对象内部的某些属性时,不会自动追踪响应。这意味着当我们需要对复杂对象的内部属性进行修改和响应式更新时,可能需要手动将这些属性声明为 ref 或者通过 .value 来显式更新。

    • 示例:ref 包裹对象时的响应式行为

      import { ref } from 'vue';export default {setup() {const user = ref({name: 'Alice',age: 25});const updateName = () => {user.value.name = 'Bob';  // 修改 user 对象内部属性};return { user, updateName };}
      };
      

      在上面的示例中,user 是一个对象,并被 ref 包裹。当我们通过 user.value.name = 'Bob' 修改内部属性时,Vue 能够正确追踪到变化,因为我们通过 .value 明确地修改了整个对象的值。

      问题:无法直接响应复杂对象内部的深层嵌套属性

      假如我们有一个更复杂的嵌套对象,直接修改嵌套属性并不会触发响应式更新。这种情况下,需要显式地通过 .valueref 来处理内部嵌套属性。

    • 示例:复杂嵌套对象需要手动处理的情况

      import { ref } from 'vue';export default {setup() {const user = ref({name: 'Alice',details: {age: 25,address: {city: 'New York'}}});const updateCity = () => {user.value.details.address.city = 'Los Angeles'; // 可能无法正确触发响应式更新};return { user, updateCity };}
      };
      

      在这个示例中,我们将 addressref 包裹,这样内部的 city 属性在被修改时,Vue 就能够自动追踪并更新视图。

      总结

    • ref 用于包装复杂对象时,整个对象是响应式的,但对象内部的嵌套属性修改可能不会自动触发响应式更新。
    • 如果需要对复杂对象或数组的内部属性进行精细化的响应式处理,应该手动将这些属性用 ref 包裹,或者通过 .value 来显式更新嵌套属性的值。
    • 这种情况提醒我们在使用 ref 包裹复杂数据时,要意识到它的局限性,并根据需求选择 refreactive 来管理响应式数据。

    • 对于简单数据类型,ref 是最直接和方便的选择;但在处理复杂对象时,特别是对象的嵌套属性时,可能需要更复杂的手动处理。
reactive 的优缺点
  • 优点
    • 语法更加直观简洁,操作时不需要 .value
    • 深度响应式,适合管理嵌套的复杂数据。
  • 缺点
    • 仅限于对象和数组,无法处理基本数据类型。
    • 不能直接解构对象,否则解构后的属性将失去响应式能力。

5. 推荐的使用场景

使用 ref 的场景
  • 处理基本数据类型:如 numberbooleanstring,可以使用 ref 来确保这些类型是响应式的。
  • 简单的 DOM 引用:在 Vue 中通过 ref 访问 DOM 元素或组件实例。
  • 包装单个值:当你需要管理基本数据类型的响应式数据时,ref 是最合适的。
  • 复杂对象需要显式封装为响应式时:如果你希望将一个对象或数组显式地转换为响应式数据,而不使用 reactive 的深度响应式特性。
使用 reactive 的场景
  • 处理复杂对象或数组:当你需要管理包含多个属性的对象或数组时,reactive 是最佳选择,因为它能够自动处理嵌套的属性和深度响应。
  • 需要更自然的对象操作:对于那些需要频繁操作属性的对象,reactive 提供更符合直觉的语法,不需要使用 .value
  • 表单数据或大规模数据操作:当管理用户表单或需要管理复杂的数据结构(如多个嵌套属性对象)时,reactive 更加灵活高效。

6. 组合使用的场景

在一些场景下,你可以同时使用 refreactive,例如你需要处理一个对象的深度响应式属性,但其中的某些属性需要用 ref 封装以实现特定的逻辑。

示例:refreactive 组合使用

import { ref, reactive } from 'vue';export default {setup() {const count = ref(0);  // 处理简单的基本数据类型const user = reactive({ name: 'Alice', age: ref(25) });  // 组合使用,user 是响应式对象,age 使用 ref 单独封装const incrementAge = () => {user.age.value++;  // 需要用 .value 修改 ref 类型的属性};return { count, user, incrementAge };}
};

总结

  • ref:适合处理基本类型(数字、字符串、布尔值等)和需要显式封装的对象/数组。使用 .value 访问和修改。
  • reactive:适合处理复杂对象和数组,并且会对所有嵌套属性进行深度响应式管理,语法上更符合直觉。

http://www.ppmy.cn/server/134719.html

相关文章

ajax 读取文件

DOMException: Failed to read the responseXML property from XMLHttpRequest: The value is only accessible if the objects responseType is or document (was blob). at XMLHttpRequest.r ( $.ajax({ url: 未来之窗_服务, method: GET, …

java版Spring Cloud+Mybatis+Oauth2+分布式+微服务+实现工程管理系统

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展,企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性,公司对内部工程管…

51单片机完全学习——DS18B20温度传感器

一、DS18B20数据手册解读 首先我们知道DS18B20使用的是单总线传输,默认情况下读出来的温度是12位的,我们这里只讨论外部电源供电这种情况。 有这张图片我们知道,12位温度的最小分辨率是10^-4次方,因此就是0.0625.我们只需要将最后…

Spring MVC(下)

博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:MySQL数据库 JavaEE专栏:JavaEE 关注博主带你了解更多JavaEE知识 目录 1.响应 1.1 返回静态页面 1.2 返回数据ResponseBody 1.3 返回HTML代码⽚段 1.4 返回JSON 1.5 设置状态码 1.6 设置Header 2 . …

docker:mysql8.0解决sql_mode = only_full_group_by问题

前言 如标题所言,我在centos上使用docker部署了mysql8.0的容器并运行,但长时间后发现该mysql的一些配置需要变更。 为了解决sql_mode only_full_group_by问题,我决定更新mysql的配置文件。 之前有讲过mysql5.7的安装方案,里面有解…

Rust小练习,编写井字棋

画叉画圈的游戏通常指的是 井字棋(Tic-Tac-Toe),是一个简单的两人游戏,规则如下: 游戏规则 棋盘:游戏在一个3x3的方格上进行。玩家:有两个玩家,一个用“X”表示,另一个…

jenkins邮件通知配置

使用jenkins做持续集成,或定时任务,都对测试执行工作非常有帮助。但完成这些工作后,用邮件通知相关责任人是jenkins的又一给力功能。 下面看下jenkins的邮件通知配置事项。 首先,打开管理jenkins, 配置下系统管理员的邮箱账号&a…

JAVA单列集合

List系列集合:添加的元素是 有序、可重复、有索引 Set系列集合:添加的元素是 无序、不重复、无索引 Collection Collection是单列集合的接口,它的功能是全部单列集合都可以继承使用的 public boolean add(E e) 把给定的对象添加到当前集合中 public void …