vue 不同版本下v-model的底层实现
下面把「底层实现」和「差异」拆开讲,先给代码级流程,再给一个对照表,面试或源码阅读都能直接用。
一、底层实现(编译→运行时的两条链路)
-
Vue 2
• 编译阶段:模板编译器遇到v-model,根据元素类型生成不同的 AST 指令对象。
• 运行时指令:src/platforms/web/compiler/directives/model.js里的model()函数把指令对象转成-
原生标签:
addProp(el, 'value', binding.value) // :value="xxx" addHandler(el, 'input', '$emit("input",$event.target.value)')如果有.lazy/.number/.trim就换事件名或加转换函数。 -
自定义组件:
addProp(el, 'value', binding.value) addHandler(el, 'input', '$emit("input",$event)')
这里事件名固定写死为input,prop 名固定写死为value。 -
-
Vue 3
• 编译阶段:在packages/compiler-dom/src/transforms/vModel.ts的transformModel()里直接把v-modelAST 节点就地替换成两条 props:-
原生标签:
{ name: 'value', value: exp } { name: 'on', arg: 'input', exp: `${exp} = $event.target.value` } -
自定义组件:
{ name: 'modelValue', value: exp } { name: 'on', arg: 'update:modelValue', exp: `${exp} = $event` }
• 运行时不再调用额外指令函数,因为 AST 已被静态展开,性能更好。 -
二、核心差异对照表
| 维度 | Vue 2 | Vue 3 |
|---|---|---|
| 触发时机 | 运行时指令处理 | 编译时 AST 替换 |
| 默认 prop | value |
modelValue |
| 默认事件 | input |
update:modelValue |
| 自定义组件 model 选项 | 需要 model: { prop:'xx', event:'yy' } |
不再需要 |
| 多 v-model | ❌ 不支持 | ✅ v-model:title 等 |
| 修饰符实现 | 在指令函数里加判断 | 在 AST 转换中加判断 |
| sync 等价写法 | .sync 修饰符 |
直接用多 v-model 取代 |
三、一句话背下来
-
Vue2:
v-model="a"→ 运行时帮你拼成:value="a"+@input="a=$event"。 -
Vue3:
v-model="a"→ 编译阶段直接换成:modelValue="a"+@update:modelValue="a=$event",并支持任意数量的v-model:xxx。
本文来自博客园,作者:Carvers,转载请注明原文链接:https://www.cnblogs.com/carver/articles/18992298

浙公网安备 33010602011771号