You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3嵌套ref问题:无法访问/赋值内部ref的value属性?

Vue 3嵌套Ref初始值为undefined/null时无法访问.value的问题

问题现象

当外层是指向对象的ref,内部嵌套的ref初始值为undefined或null时,尝试访问内部ref的.value属性会报错;但内部ref初始值为对象、数字等非空值时可正常操作,单独的ref(外层直接是undefined/null)也能正常赋值。

示例代码:

const { ref } = Vue;

let options = {
  setup: function () {
    const outer = ref({
      innerUndefined: ref(undefined),
      innerNull: ref(null),
      innerObject: ref({}),
      innerZero: ref(0)
    });
    const outerUndefined = ref(undefined);
    const outerNull = ref(null);
    
    // 尝试设置innerUndefined.value失败
    console.log('Attempting to set innerUndefined.value');
    try {
        outer.value.innerUndefined.value = { 'test': 1 };
    } catch (error) {
        console.log('FAIL: ' + error.toString());
    }
    
    // 尝试设置innerNull.value失败
    console.log('Attempting to set innerNull.value');
    try {
        outer.value.innerNull.value = { 'test': 2 };
    } catch (error) {
        console.log('FAIL: ' + error.toString());
    }
    
    // 设置innerObject.value成功
    console.log('Attempting to set innerObject.value');
    outer.value.innerObject.value = { 'test': 3 };
    console.log('SUCCESS');
    
    // 设置innerZero.value成功
    console.log('Attempting to set innerZero.value');
    outer.value.innerZero.value = { 'test': 4 };
    console.log('SUCCESS');
    
    // 设置outerUndefined.value成功
    console.log('Attempting to set outerUndefined.value');
    outerUndefined.value = { 'test': 5 };
    console.log('SUCCESS');
    
    // 设置outerNull.value成功
    console.log('Attempting to set outerNull.value');
    outerNull.value = { 'test': 6 };
    console.log('SUCCESS');
    
    return {};
  }
};

Vue.createApp(options).mount('#app');
<script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script>
<div id="app">See the console</div>

原因分析

这是Vue 3的ref自动解包机制导致的:

  • 当ref作为响应式对象(外层ref的.value会被Vue转为响应式对象)的属性时,Vue会自动对其解包,直接返回ref的.value值。
  • 对于初始值为undefined/null的内部ref,解包后得到的就是undefined/null,而非ref实例,自然没有.value属性,赋值时会报错。
  • 初始值为对象、数字的内部ref,解包后虽返回对应值,但Vue对这类类型的响应式处理逻辑会保留关联,允许通过.value反向操作原始ref;单独的ref不存在嵌套在响应式对象中的场景,不会触发自动解包,直接操作的是ref实例本身。

解决方案

方案1:提前保存内部ref到独立变量

将内部ref提前赋值给独立变量,绕过外层响应式对象的自动解包,直接通过变量操作:

const { ref } = Vue;

let options = {
  setup: function () {
    // 提前定义并保存内部ref
    const innerUndefined = ref(undefined);
    const innerNull = ref(null);
    const innerObject = ref({});
    const innerZero = ref(0);
    
    const outer = ref({
      innerUndefined,
      innerNull,
      innerObject,
      innerZero
    });
    
    // 直接通过变量操作,成功赋值
    console.log('Attempting to set innerUndefined.value via variable');
    innerUndefined.value = { 'test': 1 };
    console.log('SUCCESS');
    
    console.log('Attempting to set innerNull.value via variable');
    innerNull.value = { 'test': 2 };
    console.log('SUCCESS');
    
    return {};
  }
};

Vue.createApp(options).mount('#app');

方案2:使用markRaw阻止自动解包

用markRaw标记内部ref,让Vue不对其进行自动解包,外层响应式对象的属性会保留ref实例:

const { ref, markRaw } = Vue;

let options = {
  setup: function () {
    const outer = ref({
      innerUndefined: markRaw(ref(undefined)),
      innerNull: markRaw(ref(null)),
      innerObject: ref({}),
      innerZero: ref(0)
    });
    
    // 正常访问.value赋值
    console.log('Attempting to set innerUndefined.value with markRaw');
    outer.value.innerUndefined.value = { 'test': 1 };
    console.log('SUCCESS');
    
    console.log('Attempting to set innerNull.value with markRaw');
    outer.value.innerNull.value = { 'test': 2 };
    console.log('SUCCESS');
    
    return {};
  }
};

Vue.createApp(options).mount('#app');

方案3:外层改用shallowRef

如果不需要外层对象的深度响应式,使用shallowRef,它不会对内部对象进行响应式转换,内部ref不会被自动解包:

const { ref, shallowRef } = Vue;

let options = {
  setup: function () {
    const outer = shallowRef({
      innerUndefined: ref(undefined),
      innerNull: ref(null),
      innerObject: ref({}),
      innerZero: ref(0)
    });
    
    // 正常访问.value赋值
    console.log('Attempting to set innerUndefined.value with shallowRef');
    outer.value.innerUndefined.value = { 'test': 1 };
    console.log('SUCCESS');
    
    console.log('Attempting to set innerNull.value with shallowRef');
    outer.value.innerNull.value = { 'test': 2 };
    console.log('SUCCESS');
    
    return {};
  }
};

Vue.createApp(options).mount('#app');

内容的提问来源于stack exchange,提问作者Agendum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:23:19