v-model是语法糖,本质为prop绑定与update:xxx事件监听的组合;子组件通过emit触发update:xxx通知父组件更新数据,Vue 3.4+可用defineModel简化实现。

v-model 本身不是魔法,它只是把属性绑定和事件监听打包成一个简洁写法。Emit 和 update:propName 事件配合,才是实现双向数据流的真实链条:子组件不改父的数据,只“喊话”让父自己改。
核心机制:v-model 是语法糖,update:xxx 是通信协议
当你写 <myinput v-model="searchText"></myinput>,Vue 实际把它展开为:
- Vue 3:
<myinput :modelvalue="searchText"> searchText = val" /></myinput> - Vue 2:
<myinput :value="searchText"> searchText = val" /></myinput>
子组件要做的,就是接收对应 prop(如 modelValue),并在值变化时调用 emit('update:modelValue', newValue) —— 这个事件名必须严格匹配,Vue 才能正确触发父组件的赋值逻辑。
手动实现 update:xxx 的标准步骤
适用于 Vue 3(非 3.4+)或需要显式控制逻辑的场景:
- 子组件用
defineProps({ modelValue: String })接收值 - 用
defineEmits(['update:modelValue'])声明可触发事件 - 模板中绑定原生 input:
<input :value="modelValue"> - 父组件监听到事件后,直接赋值:
searchText = newValue,触发响应式更新
支持多个字段:v-model:title 和 update:title
一个组件可以同时管理多个受控状态,比如用户名和邮箱:
- 父组件:
<userform v-model:username="name" v-model:email="mail"></userform> - 子组件声明:
defineProps({ username: String, email: String }) - 子组件触发:
emit('update:username', 'Alice')或emit('update:email', 'a@b.com') - 每个字段独立走自己的 prop + update:xxx 通道,互不影响
Vue 3.4+ 简化方案:defineModel 一行搞定
不用手写 props、emits 和事件名,底层已封装好:
-
const model = defineModel()→ 默认绑定 modelValue,模板中直接<input v-model="model"> -
const title = defineModel('title')→ 对应 v-model:title,自动处理props.title和emit('update:title') - 修饰符(如
.number、.trim)也自动生效,无需额外判断


















