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

Vue3迁移时合并父子组件$refs报错问题求助

Vue3 中子组件 refs 合并到父组件的解决方案

Vue3 里的 $refs 是只读的 Proxy 代理对象,和 Vue2 里的普通可修改对象完全不同。直接用扩展运算符、Object.assign 去修改父组件的 $refs,会触发 Vue 的只读限制,自然会报和 $set 相关的错误。


推荐方案:自定义响应式 refs 集合

不要直接操作 $refs,在父组件里自己维护一个响应式的 refs 容器,把子组件的 refs 合并进去:

父组件代码

<template>
  <ChildComponent ref="child" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'

// 自定义的父级 refs 集合
const parentRefs = ref({})
const child = ref(null)

onMounted(() => {
  // 合并子组件的 refs 到自定义容器
  if (child.value) {
    parentRefs.value = {
      ...parentRefs.value,
      ...child.value.exposedRefs
    }
  }
})
</script>

子组件代码

<template>
  <input ref="inputRef" type="text" />
  <button ref="btnRef">按钮</button>
</template>

<script setup>
import { ref, defineExpose } from 'vue'

const inputRef = ref(null)
const btnRef = ref(null)

// 暴露自身的 refs 给父组件
defineExpose({
  exposedRefs: { inputRef, btnRef }
})
</script>

不推荐方案:绕过 Proxy 限制(仅作参考)

如果非要模拟 Vue2 的写法,可以通过获取子组件 refs 的原始属性,赋值到普通对象里,但绝对不要修改父组件的 $refs:

// 父组件 onMounted 钩子中
onMounted(() => {
  const childRawRefs = child.value.$refs
  const mergedRefs = {}
  // 遍历子组件 refs 的属性,手动挂载到普通对象
  for (const key in childRawRefs) {
    mergedRefs[key] = childRawRefs[key]
  }
  // 后续使用这个 mergedRefs 代替父组件 $refs
})

注意:Vue3 将 $refs 设为只读是有设计考量的,它仅作为直接操作 DOM/组件的便捷方式,并非响应式状态,不应该被修改。自定义响应式集合才是符合 Vue3 设计理念的做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:46:08