vue 不同版本下v-model的底层实现

下面把「底层实现」和「差异」拆开讲,先给代码级流程,再给一个对照表,面试或源码阅读都能直接用。

一、底层实现(编译→运行时的两条链路) 

  1. 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

  2. Vue 3
    • 编译阶段:在 packages/compiler-dom/src/transforms/vModel.tstransformModel() 里直接把 v-model AST 节点就地替换成两条 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

你可能感兴趣的:(vue 不同版本下v-model的底层实现)