Vue3中ref与prop同名为何仅构建阶段触发未定义报错
Vue3 同名Prop与模板Ref生产环境报错问题
问题表现
定义名为foobar的prop属性后,若创建同名模板ref,访问该ref时Vue会抛出foobar未定义的错误。该问题仅在执行npm run build构建生产包时出现,npm run dev启动开发服务时无异常。
将ref与prop设置为不同名称即可修复该问题,但官方文档未明确提及该命名限制,问题根因如下。
问题复现代码
<script setup> defineProps({ foobar: { type: String } }) </script> <template> <div> <div ref="foobar"> {{ foobar }} </div> </div> </template> <script> export default { data() { return { } }, mounted() { // 抛出错误 const el = this.$refs.foobar; } } </script>
正常运行代码示例
<script setup> defineProps({ foobar: { type: String } }) </script> <template> <div> <div ref="foobar2"> {{ foobar }} </div> </div> </template> <script> export default { data() { return { } }, mounted() { // 正常访问 const el = this.$refs.foobar2; } } </script>
根本原因
该问题由Vue3生产构建阶段的命名空间冲突导致,和开发/生产环境的编译策略差异直接相关:
- 开发环境下Vue保留完整运行时逻辑,prop存储在组件实例的
props字段、模板ref存储在$refs字段,二者完全隔离,同名不会产生冲突,因此访问正常。 - 生产构建时Vue会启用编译优化,
<script setup>中声明的prop会被直接提升为组件实例的顶层访问属性,减少属性查找路径以提升运行性能;此时如果模板ref和prop同名,编译阶段会误将ref的绑定目标识别为已经存在的prop变量,不会将对应的DOM节点写入$refs对象,最终访问this.$refs.foobar时就会得到undefined。 - 该冲突仅出现在同时使用
<script setup>和选项式<script>块的场景:如果全部逻辑都写在<script setup>中,编译阶段会检测到同名冲突直接抛出编译警告,但跨script块通过this.$refs访问时,编译阶段不会做跨块的命名校验,因此问题只会在生产构建后暴露。
Vue2的prop和ref存储逻辑完全独立,不存在该同名冲突问题。
内容的提问来源于stack exchange,提问作者Jamie Bradley
相关产品推荐
相关产品推荐

