ref() 和 reactive()响应性 浅解

server/2025/2/22 0:43:09/

文章目录

    • 1. `ref()` 和 `reactive()` 的区别
    • 2. `解构` 详解
      • 2.1. 什么是解构
      • 2.2. 解构避免丢失响应性的办法
        • 2.2.1. 解决方案:`toRefs()` 保持响应性
        • 2.2.2. 解决方案: `toRef()`保持响应性
    • 3. 最佳实践

在 Vue 3 中,ref()reactive() 都是用于响应式数据管理的 API,它们的主要作用是让数据具有响应性,使 Vue 组件在数据变化时能够自动更新视图。它们有一定的关联,但用法和适用场景有所不同。


1. ref()reactive() 的区别

对比点ref()reactive()
适用场景适用于基本类型(Number、String、Boolean)和对象适用于对象(Object、Array、Map、Set等)
是否需要 .value需要:count.value不需要,直接访问属性:state.count
是否可以解构不能直接解构,会丢失响应性不能直接解构,会丢失响应性
适用于数组/对象适用于任意类型的数据,但访问对象时需要 .value适用于复杂的对象和数组
底层实现ref 内部使用 reactive 处理对象使用 Proxy 代理对象,实现响应性

2. 解构 详解

情况示例是否丢失响应性?原因解决方案
ref(基本类型)const count = ref(0);
count.value++
不会count 本身是 ref,Vue 追踪 count.value直接 count.value++
ref(对象类型) 并直接修改 .valueconst user = ref({ name: 'Alice' });
user.value.name = 'Bob';
不会user.value 仍然是响应式对象直接修改 user.value.name
解构 ref(对象).valueconst { name } = user.value;
name = 'Bob';
会丢失name 是普通变量,Vue 不再追踪使用 toRefs(user.value)
解构 reactive(对象)const user = reactive({ name: 'Alice' });
const { name } = user;
name = 'Bob';
不会reactive 生成的是 Proxy,解构后仍然保持响应性直接解构 const { name } = user;
reactive 对象包含 ref()const user = reactive({ name: ref('Alice') });
user.name = 'Bob';
不会user.nameref,Vue 能追踪 user.name.value访问 user.name.value
reactive 里存 ref 并解构const user = reactive({ name: ref('Alice') });
const { name } = user;
name = 'Bob';
会丢失name 变成 ref,但解构后 Vue 不会追踪 name.value改为 toRef(user, 'name')
解构 reactive() 并使用 toRefs()const user = reactive({ name: 'Alice' });
const { name } = toRefs(user);
不会toRefs()user.name 转换为 ref,仍然响应式继续 name.value = 'Bob'

2.1. 什么是解构

解构是 JavaScript用于从对象或数组中提取值的语法,允许你将数据拆分并存储到独立的变量中。
看个例子,一眼便知

<script setup>
import { reactive } from 'vue';const state = reactive({count: 0,message: 'Hello'
});// ❌ 直接解构(会丢失响应性)
let { count, message } = state;const increment = () => {count++; // ❌ 这里不会触发视图更新
};
</script><template><p>{{ count }}</p> <!-- 不会更新 --><button @click="increment">+</button>
</template>

2.2. 解构避免丢失响应性的办法

在 Vue 3 中,reactive() 返回的对象在解构后会丢失响应性,这是因为 reactive() 使用的是 Proxy,而解构时只会拷贝属性值,而不会保留 Proxy 代理能力。

2.2.1. 解决方案:toRefs() 保持响应性
  • toRefs(state) state 的每个属性变成 ref(),这样解构出来的 countmessage 就是 ref,修改 .value 仍然会触发 Vue 的响应式系统。

toRefs() 用于将 reactive 对象的属性转换成 ref,这样解构后仍然保持响应性:

<script setup>
import { reactive, toRefs } from 'vue';const state = reactive({count: 0,message: 'Hello'
});// ✅ 使用 toRefs() 让解构后的变量仍保持响应性
const { count, message } = toRefs(state);const increment = () => {count.value++; // ✅ 这里会触发视图更新
};
</script><template><p>{{ count }}</p> <!-- 视图会更新 --><button @click="increment">+</button>
</template>
2.2.2. 解决方案: toRef()保持响应性

如果你只想让某个属性保持响应性,而不是整个 state,可以使用 toRef()

<script setup>
import { reactive, toRef } from 'vue';const state = reactive({count: 0,message: 'Hello'
});// ✅ 只把 count 变成 ref
const count = toRef(state, 'count');const increment = () => {count.value++; // ✅ 仍然是响应式的
};
</script><template><p>{{ count }}</p><button @click="increment">+</button>
</template>

3. 最佳实践

  • 基本类型ref()
  • 对象reactive()
  • 解构 reactive ➝ 用 toRefs()
  • 解构 ref(对象).value不能直接解构,必须用 toRefs()

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

相关文章

iOS 中使用 FFmpeg 进行音视频处理

在 iOS 中使用 FFmpeg 进行音视频处理,通常需要将 FFmpeg 的功能集成到项目中。由于 FFmpeg 是一个 C 库,直接在 iOS 中使用需要进行一些配置和封装。 1. 在 iOS 项目中集成 FFmpeg 方法 1:使用 FFmpeg 预编译库 下载 FFmpeg iOS 预编译库: 可以从以下项目中获取预编译的 …

拆解微软CEO纳德拉战略蓝图:AI、量子计算、游戏革命如何改写未来规则!

2025年2月19日 知名博主Dwarkesh Patel对话微软CEO萨蒂亚纳德拉 在最新访谈释放重磅信号&#xff1a;AI将掀起工业革命级增长&#xff0c;量子计算突破引爆材料科学革命&#xff0c;游戏引擎进化为世界模拟器。 整个视频梳理出几大核心观点&#xff0c;揭示科技巨头的未来十年…

el-message自定义HTML包含按钮点击事件

关键代码 ElMessage({dangerouslyUseHTMLString: true,message: <span>请先维护供暖季信息</span> <el-button click${{go}} type"success" size"small" id"message-button">立即设置</el-button>,type: "error…

请解释一下Standford Alpaca格式、sharegpt数据格式-------deepseek问答记录

1 Standford Alpaca格式 json格式数据。Stanford Alpaca 格式是一种用于训练和评估自然语言处理&#xff08;NLP&#xff09;模型的数据格式&#xff0c;特别是在指令跟随任务中。它由斯坦福大学的研究团队开发&#xff0c;旨在帮助模型理解和执行自然语言指令。以下是该格式的…

python中格式化输出知识点汇总

在Python中&#xff0c;格式化输出是一种常见的操作&#xff0c;用于将数据以特定的格式展示。以下是Python中格式化输出的主要方法&#xff1a; 1. 使用 % 操作符 这是Python早期版本中常用的格式化方法&#xff0c;类似于C语言中的 printf 。 基本语法 &#xff1a; "…

leetcode 2435. 矩阵中和能被 K 整除的路径

题目如下 数据范围 本题同样是由于一个坐标对应的状态数不唯一所以需要三维数组来存储状态并转移。 显然我们无需关心具体的数只需要计算余数即可&#xff08;&#xff08;a b&#xff09;% k a % k b % k&#xff09; 所以我们用余数的可能取值(0 到 k - 1)作为状态。通…

开放表格式和对象存储架构指南

比较 Apache Iceberg、Delta Lake 和 Apache Hudi&#xff0c;并了解如何为您的数据湖仓一体选择合适的开放表格式。开放表格式和对象存储正在重新定义组织构建其数据系统的方式&#xff0c;为可扩展、高效且面向未来的数据湖仓一体奠定了基础。通过利用对象存储的独特优势&…

代码管理git详细使用教程及最佳实践路径

一、Git介绍 Git 是一个 分布式版本控制系统&#xff0c;用于跟踪代码变更、管理代码历史、并支持多人协作开发。它由 Linus Torvalds 在 2005 年为 Linux 内核开发而创建&#xff0c;现在已经成为软件开发的标准工具。Git的关键概念如下&#xff1a; 概念含义仓库&#xff0…