下面给你一份 真正到位、从源码原理到最佳实践全覆盖
《Vue 中 v-model 的双向绑定实现原理(含 Vue2 / Vue3 最佳实践)》

这份内容你可以直接用来写技术博客、面试准备、或者项目优化。


🚀 1. v-model 本质是什么?

一句话:

v-model = value + input(Vue2)
v-model = modelValue + update:modelValue(Vue3)

它只是一个 语法糖,把 父组件 → 子组件传值(props)
子组件 → 父组件事件回传(emit) 组合在一起,实现双向绑定。


📌 2. Vue2 & Vue3 的 v-model 区别(秒懂对比)

框架接收 prop触发事件说明
Vue2valueinput无命名 v-model
Vue3modelValueupdate:modelValue支持多 v-model

⭐ 3. Vue2 v-model 原理(完整讲解 + 代码)

📌 父组件使用

<CustomInput v-model="msg" />

v-model 等价于:

<CustomInput :value="msg" @input="msg = $event" />

📌 子组件(实现双向绑定)

export default {
  props: ["value"],
  methods: {
    onInput(e) {
      this.$emit("input", e.target.value);
    }
  }
}

原理总结(Vue2)

  1. v-model 自动给子组件传入 value
  2. 子组件改动后发出 input 事件
  3. 父组件监听 input,更新绑定变量

⭐ 4. Vue3 v-model 原理(推荐写法)

📌 父组件使用

<MyInput v-model="msg" />

等价于:

<MyInput :modelValue="msg" @update:modelValue="msg = $event" />

📌 子组件写法(Vue3 最佳实践)

<script setup>
const props = defineProps({
  modelValue: String
})

const emit = defineEmits(['update:modelValue'])

function onInput(e) {
  emit('update:modelValue', e.target.value)
}
</script>

原理总结(Vue3)

  • modelValue 是固定属性名
  • update:modelValue 是固定事件名
  • 组件中只需要 emit 即可

⭐ 5. Vue3 多 v-model(高级用法 / 面试常问)

<MyPick v-model:title="title" v-model:checked="checked" />

等价于:

<MyPick 
  :title="title" 
  @update:title="title = $event"
  :checked="checked"
  @update:checked="checked = $event"
/>

子组件代码:

defineProps(['title', 'checked'])
defineEmits(['update:title', 'update:checked'])


🔥 6. v-model 的核心实现逻辑(框架底层)

Vue 做的关键事情:

  1. 生成一个 prop(value/modelValue)
  2. 生成一个事件(input/update:modelValue)
  3. 父组件表达式绑定msg = $event
  4. Watcher 监听 + 响应式更新视图

核心思想:

“父传属性 + 子触发事件 = 双向绑定”


🧠 7. 内部原理(深入版,但通俗易懂)

Vue2 :

v-model 编译为:

model: {
  value: (msg),
  callback: function ($$v) { msg = $$v }
}

在生成 vnode 时:

  • 绑定 value 属性
  • 绑定 input 监听
  • Watcher 触发 set → notify 更新 DOM

Vue3:

使用 Proxy 的响应式系统:

const state = reactive({ msg: "" })

v-model 绑定的 modelValue 会自动变成 依赖收集的响应式值

组件 emit 更新 → 外层 state 更新 → 触发 effect → UI 渲染。


🧩 8. v-model 最佳实践(高级开发必看)


✔ 1)组件内部永远不要直接修改 props

错误 ❌:

props.modelValue = xx

正确 ✔:

emit('update:modelValue', newValue)


✔ 2)如果你需要内部状态,使用“受控 + 非受控混合模式”

const innerValue = ref(props.modelValue)

watch(() => props.modelValue, v => innerValue.value = v)

适用于输入框、防抖请求、表单组件等。


✔ 3)自定义事件命名必须遵守 Vue3 标准格式

update:modelValue
update:xxx

否则 v-model 不会生效。


✔ 4)封装表单组件时,永远推荐使用:Vue3 多 v-model

避免用 props.xxx + emit('xxx-update') 这种老模式。


🎯 9. 面试回答模板(30 秒完美回答)

你可以这样背:

在 Vue 中 v-model 是语法糖。
Vue2 通过 value + input 实现,Vue3 通过 modelValue + update:modelValue 实现。
本质是父组件向子组件下发 props,子组件通过事件通知父组件更新数据,从而实现双向绑定。
Vue3 支持多个 v-model,同时语义更清晰。
推荐使用 emit(‘update:modelValue’) 这种标准写法。