Emit 实现表单验证的核心是输入框主动上报变化,由父组件统一校验;相比 v-model 的语法糖局限,Emit 支持失焦、实时、提交等多时机控制,配合 rules 传入和 validate 暴露,实现解耦与可控。

用 Emit 实现表单验证,核心不是“发事件”,而是让输入框把变化主动告诉父组件,由父组件统一做校验逻辑——这样既解耦又可控。
为什么用 Emit 而不是 v-model?
v-model 本质是语法糖(:value + @input),但表单验证需要更精细的时机控制:比如失焦才校验、输入中实时反馈、提交时批量触发。Emit 让你自由决定什么时候抛出什么数据,比如 update:value、validate、blur,比绑定一个值更灵活。
封装带验证的输入框(基础版)
先写一个支持必填、邮箱格式校验的 MyInput 组件:
- 接收 rules prop(如
[{ required: true }, { type: 'email' }]) - 内部用 ref 存当前值,@input 触发
update:value同步父级 - 暴露 validate 方法,供父组件调用(例如点击提交时)
- 失焦时自动 emit blur,父组件可监听并触发单个校验
关键:校验逻辑不写死在组件里
校验规则和提示文案应由父组件传入,子组件只负责执行和反馈结果。例如:
- 子组件 emit
{ valid: false, message: '邮箱格式不正确' } - 父组件监听
@validate-result,收集所有字段结果,决定是否允许提交 - 避免在子组件里写
ElMessage.error或弹窗——那是业务层的事
配合 Form 组件统一管理(进阶)
如果项目有多个表单项,可以再封装一个 MyForm:
- 用 provide/inject 把校验方法注入所有子
MyInput - 每个
MyInput在 mounted 时向 Form 注册自己(id + validate 方法) - Form 提供 validate() 方法,遍历所有注册项并汇总结果
- 此时
@submit.prevent="form.validate()"就能一键触发全量校验
不复杂但容易忽略:Emit 是桥梁,不是终点;验证逻辑归属父组件或 Form 容器,输入框只做“采集+上报”。

















