Provide/Inject 是 Vue 跨层级通信方案,父组件通过 provide 暴露验证上下文(registerField、validate、errors 等),子组件 inject 后注册自身校验逻辑并响应式显示错误,支持异步校验与动态规则更新。

Provide/Inject 是 Vue 中实现跨层级组件通信的有效方式,特别适合表单验证这类“父表单 → 子输入项”的场景:父组件提供统一的验证触发、状态收集和错误反馈能力,子组件(如 MyInput、MySelect)只需注入并注册自身验证逻辑,无需 props 层层透传或事件反复派发。
父组件提供验证上下文(provide)
在父级表单组件(如 MyForm)中,用 provide 暴露一个响应式对象,包含:
- registerField:供子组件调用,传入字段名、校验函数、初始值等;
-
validate:手动触发全量校验,返回
{ valid: boolean, errors: Record;} - errors:当前所有字段的错误消息(响应式),供子组件或父模板显示;
- setFieldError(可选):支持子组件主动上报错误(例如异步校验完成)。
使用 reactive + onBeforeUnmount 清理注册项,避免内存泄漏。
子组件注入并注册验证逻辑(inject)
每个自定义表单项(如 MyInput)在 setup 中 inject 父提供的上下文,并在 onMounted 或 onBeforeMount 中调用 registerField:
- 传入唯一
name(建议与 v-model 绑定的字段一致); - 传入校验函数
validator: () => string | undefined(返回错误信息字符串,undefined 表示通过); - 可选传入
value和required标志,用于基础规则判断; - 内部监听自身输入变化,调用
context.validateField(name)(若提供)或等待父级统一触发。
子组件可通过 context.errors[name] 获取当前错误,绑定到 {{ errors[name] }} 即可实时反馈。
支持异步校验与动态规则
当校验依赖接口(如用户名是否已存在),子组件不应阻塞提交流程。推荐做法:
- 校验函数返回
Promise; - 父级
validate方法自动 await 所有 Promise,合并结果; - 注入的上下文可额外暴露
isFieldValidating: Ref,子组件用> v-show="isFieldValidating[name]"显示 loading; - 规则变更时(如邮箱字段切换为手机号),子组件重新调用
registerField覆盖旧注册项(需先 unregister 或用 name 冲突检测)。
注意事项与边界处理
Provide/Inject 默认不响应式,必须用 reactive 或 ref 包裹对象;父子组件需确保 provide 在子组件 inject 前已完成初始化(避免 undefined);
- 避免在
setup顶层直接解构注入对象(会丢失响应性),应保持对context的引用或使用toRefs; - 多个表单嵌套时,用
Symbol作为 provide key 防止命名冲突; - 子组件卸载前应调用
unregisterField(name)(如有),清理缓存,否则重复挂载可能重复注册; - 不建议在 inject 中修改父级 provide 的原始数据,应通过明确方法(如
setFieldError)交互。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











