ref 解包细节

作为 reactive 对象的属性

一个 ref 会在作为响应式对象的属性被访问或修改时自动解包。换句话说,它的行为就像一个普通的属性:

复制代码
const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

如果将一个新的 ref 赋值给一个关联了已有 ref 的属性,那么它会替换掉旧的 ref:

复制代码
const otherCount = ref(2)

state.count = otherCount
console.log(state.count) // 2
// 原始 ref 现在已经和 state.count 失去联系
console.log(count.value) // 1

只有当嵌套在一个深层响应式对象内时,才会发生 ref 解包。当其作为浅层响应式对象的属性被访问时不会解包。

数组和集合的注意事项

与 reactive 对象不同的是,当 ref 作为响应式数组或原生集合类型 (如 Map) 中的元素被访问时,它不会被解包:

javascript 复制代码
const books = reactive([ref('Vue 3 Guide')])
// 这里需要 .value
console.log(books[0].value)

const map = reactive(new Map([['count', ref(0)]]))
// 这里需要 .value
console.log(map.get('count').value)

在模板中解包的注意事项

在模板渲染上下文中,只有顶级的 ref 属性才会被解包。

在下面的例子中,countobject 是顶级属性,但 object.id 不是:

javascript 复制代码
const count = ref(0)
const object = { id: ref(1) }

因此,这个表达式按预期工作:

javascript 复制代码
{{ count + 1 }}

...但这个不会

javascript 复制代码
{{ object.id + 1 }}

渲染的结果将是 [object Object]1,因为在计算表达式时 object.id 没有被解包,仍然是一个 ref 对象。为了解决这个问题,我们可以将 id 解构为一个顶级属性:

javascript 复制代码
const { id } = object
{{ id + 1 }}

现在渲染的结果将是 2

另一个需要注意的点是,如果 ref 是文本插值的最终计算值 (即 {``{ }} 标签),那么它将被解包,因此以下内容将渲染为 1

javascript 复制代码
{{ object.id }}

该特性仅仅是文本插值的一个便利特性,等价于 {``{ object.id.value }}

相关推荐
软件技术NINI2 分钟前
JavaScript性能优化实战指南
前端·css·学习·html
前端小配角28 分钟前
React难上手原因找到了,原来是因为坑太多了。。。
前端
是你的小橘呀29 分钟前
零基础也能懂!React Hooks实战手册:useState/useEffect上手就会,告别类组件
前端·架构
xhxxx30 分钟前
从样式到结构:TailwindCss + Fragment 如何让 React 代码更干净、更高效
前端·css·react.js
Maxkim32 分钟前
「✍️JS原子笔记 」深入理解JS数据类型检测的4种核心方式
前端·javascript·面试
小高00733 分钟前
Elips-Core:轻量级 Node.js Web 框架核心实现
前端·javascript·node.js
Focus_36 分钟前
SSE+broadcastChannel
前端
zabr38 分钟前
前端已死?我用 Trae + Gemini 零代码手搓 3D 塔罗牌,找到了新出路
前端·人工智能·aigc
Aotman_39 分钟前
Vue MutationObserver 监听
前端·javascript·vue.js·elementui·前端框架·ecmascript
专注前端30年43 分钟前
Vue3的生命周期钩子有哪些变化?
前端·javascript·vue.js