Vue3+Element Plus项目ref绑定问题,慎用Proxy

22 阅读2分钟

问题描述:今天在做一个发送消息的弹窗,弹窗里边输入的内容总是为空。

1.输入内容以后没有立即显示;

2.删除效果呈现的是删除不了;

3.失焦以后显示出来了,看似显示有值,接口的入参却为""

问题原因

Vue3 中 <script setup> 语法对 getCurrentInstance().proxy 的限制,导致通过 proxy 获取的 $refs 不稳定或指向错误的实例

详细解析

  1. getCurrentInstance().proxy<script setup> 中的局限性 在 Vue3 中,getCurrentInstance() 用于获取当前组件实例,其返回的 proxy 对象类似 Vue2 中的 this,可访问组件的 $refs$emit 等方法。但在 <script setup> 语法中: - <script setup>编译时语法糖,会对组件内部变量进行封装,对外隐藏细节(如 this 上下文)。 - proxy 的获取依赖组件实例的生命周期,若在实例未完全初始化时访问(或因框架版本差异),可能导致 proxy 指向不完整的实例,甚至 undefined
  2. 在你的代码中,proxy.$refs.messageForm 可能存在两种问题: - $refs 未正确绑定proxy 引用的实例与模板中的 ref="messageForm" 不同步,导致 proxy.$refs.messageFormundefined(但未报错,可能框架做了容错)。 - 验证方法调用异常:即使获取到 messageFormproxy 上下文的差异可能导致 validate 方法内部的响应式依赖失效(如无法正确读取 messageForm.content 的值),表现为“输入不显示”“验证不触发”“接口不调用”等。
  3. ref 直接引用表单的优势 当你改用 const messageFormRef = ref(null) 并在模板中绑定 ref="messageFormRef" 时: - 直接绑定组件实例messageFormRef 是 Vue3 推荐的引用方式,通过 ref 变量直接指向表单组件实例,跳过了 proxy 这一中间层,避免了实例引用不稳定的问题。 - 类型安全与响应式messageFormRef.value 能准确获取表单组件的 validate 方法,且方法内部的上下文与组件一致,可正确访问 model 绑定的 messageForm 数据,确保验证逻辑、输入绑定正常工作。
  4. 为什么解决了“输入不显示”和“删除不掉”? - 输入显示问题el-inputv-model 绑定依赖表单组件的内部状态管理,当 proxy 引用异常时,表单可能无法正确同步 messageForm.content 的变化到输入框视图。改用 messageFormRef 后,表单组件状态与数据绑定正常,输入内容能实时渲染。 - 删除操作问题:删除依赖输入框的 input 事件与表单的状态同步,proxy 异常可能导致事件回调未正确触发。messageFormRef 确保事件流完整,删除操作能正常更新 messageForm.content 并反馈到视图。
  5. Vue3 官方推荐的用法 Vue3 文档明确建议:在 <script setup> 中,应使用 ref 变量直接获取 DOM 或组件引用,而非依赖 getCurrentInstance().proxy。例如: html <!-- 模板 --> <el-form ref="messageFormRef" ... /> javascript // 脚本 import { ref } from 'vue'; const messageFormRef = ref(null); // 调用方法 messageFormRef.value.validate(...) 这种方式更符合 Vue3 的响应式设计,且避免了 proxy 带来的上下文不确定性。

总结

建议使用:messageFormRef.value.validate

目前不建议使用:proxy.$refs.messageForm.validate