基于本文回答
0
评论

v-model 的实现原理?

知识点图片

v-model 的本质是 语法糖。它背后并不是什么神奇的魔法,而是 Vue 编译器在编译阶段将其转换成了 属性绑定(Props)事件监听(Events) 的组合。

简单来说,v-model 实现双向绑定的核心原理遵循 “数据向下流动(Props),事件向上冒泡(Events)” 的单向数据流原则。

我们可以分 原生 DOM 元素自定义组件 两种情况来深入理解,同时也要注意 Vue 2 和 Vue 3 的区别


1. 作用在原生 DOM 元素上 (如 <input>)

当你在 HTML 标签上使用 v-model 时,Vue 编译器会根据标签的类型自动展开为不同的属性和事件监听。

基本原理(以文本框为例)

html
<!-- 写法 -->
<input v-model="searchText" />

<!-- 编译后的等价代码 (原理) -->
<input
  :value="searchText"
  @input="searchText = $event.target.value"
/>
  1. Bind (绑定): 将数据 searchText 绑定到 input 的 value 属性上。
  2. On (监听): 监听 input 的 input 事件,当用户输入时,获取 $event.target.value 并重新赋值给 searchText

不同元素的差异

Vue 内部会根据元素类型智能处理:

  • text / textarea: 使用 value 属性 和 input 事件。
  • checkbox / radio: 使用 checked 属性 和 change 事件。
  • select: 使用 value 属性 和 change 事件。

特殊处理:中文输入法 (IME)

在输入中文(拼音)、日文等需要组合输入的语言时,原生的 input 事件会在你每敲击一次键盘时触发(比如输入 "nihao" 还没选词时)。
Vue 对此做了特殊处理:

  • Vue 监听了 compositionstart (开始输入法输入) 和 compositionend (结束输入法输入) 事件。
  • compositionstart 触发后,Vue 会设置一个标志位,暂停 v-model 的数据更新。
  • 直到 compositionend 触发(即选词完成),才会触发数据的更新。

2. 作用在自定义组件上

在组件上使用 v-model 是实现父子组件通信的一种规范模式。这里 Vue 2 和 Vue 3 有明显的区别。

Vue 3 中的实现原理

Vue 3 默认使用 modelValue 作为 prop,update:modelValue 作为事件。

父组件使用:

html
<ChildComponent v-model="message" />

<!-- 编译后的等价代码 -->
<ChildComponent
  :modelValue="message"
  @update:modelValue="newValue => message = newValue"
/>

子组件实现:

javascript
// ChildComponent.vue
defineProps(['modelValue'])
defineEmits(['update:modelValue'])

function onInput(e) {
  // 触发事件,将新值传回父组件
  emit('update:modelValue', e.target.value)
}

Vue 3 还支持多个 v-model (如 v-model:title,对应 prop title 和事件 update:title)。

Vue 2 中的实现原理

Vue 2 默认使用 value 作为 prop,input 作为事件。

父组件使用:

html
<ChildComponent v-model="message" />

<!-- 编译后的等价代码 -->
<ChildComponent
  :value="message"
  @input="newValue => message = newValue"
/>

Vue 2 的 model 选项:
如果子组件里 value 属性已经被占用了(比如 checkbox 组件),可以通过 model 选项修改默认的 prop 和 event 名:

javascript
export default {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  // ...
}

3. 总结

v-model 的实现原理一句话总结:

v-model 是 Vue 提供的语法糖,在编译时会被转换为 属性绑定(Props,如 valuemodelValue)和 事件监听(Events,如 inputupdate:modelValue)。它通过监听用户的输入事件来更新数据,并通过属性绑定将数据回显到视图上,从而实现双向绑定。

关键点速记:

  1. 语法糖:编译成 :prop + @event
  2. 原生元素:根据 type 不同,绑定 value/checked 和监听 input/change
  3. IME 问题:利用 compositionstart/end 解决中文输入过程中的频繁更新问题。
  4. 组件差异
    • Vue 2: :value + @input
    • Vue 3: :modelValue + @update:modelValue
右滑查看面试常问