v-model 是编译阶段的语法转换,非运行时魔法;它将原生元素转为 modelValue prop 和 update:modelValue 事件,自定义组件需遵循 modelValue/update:modelValue 协议,支持多 v-model 参数及编译时响应式优化。

v-model 不是运行时魔法,而是编译阶段就完成的语法转换。Vue 的模板编译器(如 Vue 3 的 `@vue/compiler-dom`)在解析模板时,会直接将 v-model 指令重写为显式的 prop 绑定 + 事件监听,不依赖运行时动态判断。
原生表单元素:自动映射为 modelValue + update:modelValue
对 <input>、<textarea>、<select> 等原生元素,编译器识别 v-model 后,会生成:
-
prop 绑定:
:modelValue="xxx"(替代旧版的:value) -
事件监听:
@update:modelValue="xxx = $event"(替代旧版的@input或@change)
例如:<input v-model="name"> 编译后等价于:
自定义组件:按约定生成 props 和 emit 规范
当作用于自定义组件时,编译器不会做类型推断,而是严格遵循 Vue 的组件 v-model 协议:
- 默认查找名为
modelValue的 prop(若未显式声明model选项) - 默认监听名为
update:modelValue的事件 - 若组件通过
defineModel()(Vue 3.4+)或defineProps({ modelValue: ... })+defineEmits(['update:modelValue'])声明,则编译结果与运行时类型检查对齐
这意味着:没有正确声明 modelValue prop 或未 emit('update:modelValue') 的组件,v-model 将静默失效——不是报错,而是退化为只读绑定。
多 v-model 支持:编译器解析修饰符并生成独立绑定
像 v-model:name 或 v-model:count 这类带参数的写法,编译器会分别提取参数作为 key:
-
v-model:name→:name="username"+@update:name="username = $event" -
v-model:count→:count="num"+@update:count="num = $event"
这使得一个组件可同时响应多个双向绑定字段,且每个字段完全解耦,互不影响。
编译时优化:跳过冗余响应式追踪
Vue 3 编译器还会结合响应式系统做轻量优化。例如,当 v-model 绑定的是 ref(如 ref('')),编译输出会直接访问 .value;若绑定的是 reactive 对象属性(如 form.name),则生成 proxy 访问路径,避免不必要的嵌套 getter 调用。
这种深度集成让 v-model 看似简洁,实则每一步都由编译器精准控制,既保障语义清晰,又兼顾运行时性能。

















