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
相关产品推荐
相关产品推荐

