Vue模板Ref解包疑问:非响应式对象存Ref后取值为undefined
问题分析与解答
为什么myObj.myRef会返回undefined
你初始化时给myObj.myRef赋值了一个ref(null)实例,但在模板的:ref回调里直接执行了myObj.myRef = el——这一步覆盖了原本的ref实例,把它变成了普通的DOM/组件实例变量(挂载完成后是目标元素/组件,卸载时会被设为undefined)。如果挂载后访问仍得到undefined,大概率是访问时机不对,比如在组件未完成挂载时就读取,或者组件已卸载触发了回调的undefined赋值。
:ref="..."的实际操作逻辑
当你用:ref绑定函数时,这个函数会在两个时机被调用:
- 组件/元素挂载完成后:传入对应的DOM元素或组件实例作为参数
- 组件/元素卸载时:传入
undefined作为参数
关于你疑惑的ref解包逻辑:只有当ref处于响应式上下文(比如reactive对象、setup返回的响应式变量)中时,模板才会自动解包它的.value。但你的myObj是非响应式对象,模板不会对myObj.myRef做解包处理——不过你这里用的是函数式ref,本质是直接执行赋值逻辑,核心问题是错误覆盖了ref实例,而非更新它的.value。
正确写法
如果要把元素引用存到非响应式对象的ref里,应该更新ref的.value而非替换ref实例:
const myObj = { myRef: ref(null), // ...其他属性 }
<template> <!-- ... --> <Comp :ref="(el) => { myObj.myRef.value = el }"/> <!-- ... --> </template>
这样myObj.myRef始终是ref实例,挂载后它的.value就会是对应的组件实例(需在挂载完成后访问,比如onMounted钩子中)。
如果不需要响应式追踪引用,也可以直接把myObj.myRef初始化为null,不用ref:
const myObj = { myRef: null, // ...其他属性 }
<template> <!-- ... --> <Comp :ref="(el) => { myObj.myRef = el }"/> <!-- ... --> </template>
这种情况下,挂载后myObj.myRef就是组件实例,卸载后变为undefined,适合无需响应式的场景。
内容的提问来源于stack exchange,提问作者cryfur
相关产品推荐
相关产品推荐

