v-model 在自定义组件中需严格遵循 Vue 3 的 modelValue prop 与 update:modelValue 事件协议,通过 defineProps 接收、defineEmits 声明,并在事件回调中 emit 明确值;支持修饰符需手动处理;Vue 3.4+ 可用 defineModel 简化。

v-model 在自定义输入组件中规范事件分发,核心是严格遵循 Vue 3 的「prop + update:xxx 事件」协议,不能沿用 Vue 2 的 value/input 惯性思维。只要 props 名、事件名、触发时机三者对齐,父组件就能自动完成双向同步。
必须接收 modelValue prop 并声明 update:modelValue emit
Vue 3 中 v-model 默认绑定的 prop 名固定为 modelValue,对应触发的事件名固定为 update:modelValue。子组件需显式声明:
- 使用
defineProps({ modelValue: { type: String, default: '' } })接收值 - 使用
defineEmits(['update:modelValue'])声明可派发事件 - 不声明 emit 会导致控制台警告,且父组件无法响应更新
input 事件内必须 emit 更新,而非直接修改 props
props 是只读的,任何直接赋值(如 props.modelValue = 'xxx')都会报错或静默失败。正确做法是在原生 @input 或 @change 回调中调用 emit:
<input :value="modelValue">- 若需处理 number、trim 等修饰符,应在 emit 前做转换:
$emit('update:modelValue', Number($event.target.value)) - 避免在 emit 中传入 event 对象本身,应提取明确值(如
$event.target.value),否则父组件接收的是 DOM Event,不是预期数据
支持修饰符时,需在 emit 前手动解析
v-model 修饰符(如 .trim、.number)不会自动透传到子组件,而是由编译器在父组件模板中生成预处理逻辑。但自定义组件中若想兼容,需主动判断并处理:
立即学习“前端免费学习笔记(深入)”;
- 父组件写法:
<custominput v-model.trim="searchText"></custominput> - 子组件内部无需感知修饰符名,但可在 emit 前加逻辑:
const val = $event.target.value.trim(); $emit('update:modelValue', val) - 更健壮的方式:通过
defineProps接收布尔型 prop(如trim: Boolean)控制是否执行 trim,实现可配置行为
Vue 3.4+ 推荐用 defineModel 简化写法
如果项目已升级至 Vue 3.4 或更高版本,可用 defineModel() 宏替代手动 props + emit:
const modelValue = defineModel({ type: String, default: '' })- 直接读写
modelValue.value,赋值即自动触发 update:modelValue - 底层仍等价于 computed 的 get/set + emit,但语法更简洁、不易出错
- 注意:defineModel 需配合
defineOptions({ model: { prop: 'modelValue', event: 'update:modelValue' } })才能支持自定义名称


















