Vue2源码【8-2】v-model

v-model相关的源码,其实极其复杂。这里主要用文本来概括流程,并且挖掘一些特别的点。

可以划分为“v-model 在控件的实现”和“v-model 在自定义组件的实现”两部分。

双向绑定:还是要依赖 数据劫持 来实现

原理: 拦截监听数据变化,更新到input控件上 + 监听input控件的键入事件,同步到数据上。

先来总结一下v-model的特点

在 Vue3之后,v-model这个模块的语法更加灵活而且便捷,基本上只是增加了上层封装而已。

  • v-model的本质就是语法糖,但是运行时也做了一些微小的优化
  • v-model即可以支持原生表单元素,也可以支持自定义组件。
  • 对于自定义组件的v-model,我们是可以配置子组件接收的 prop 名称,以及派发的事件名称。

v-model 在控件的实现

这个流程其实就是很复杂的数据存取。总之,解析语法糖,转译之后的效果:

<input
  v-bind:value="message"
  v-on:input="message=$event.target.value">

这个转译代码的流程,有时候会添加composing相关的代码到结果中:

v-model还是和单纯“value + @input”有区别,比如中文打字到一半还没按空格,v-model不会获取到,而后者会做“预输入延迟更新”,即延迟触发input

总结:onCompositionStart + onCompositionEnd + 自定义e.target.composing来控制是否手动触发input事件

  • 【-----------中文打字到一半还没按空格--------------------】
    • onCompositionStart触发,令e.target.composing = true
    • 【正常打入中文】
    • onCompositionEnd触发,发现true才往下走,先重置掉e.target.composing,然后手动触发一个假input事件并dispatchEvent(e)
    • 若没有“因为e.target.composing的flag而return终止”,然后引发 message = $event.target.value
    • 【官网】 对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。

v-model 在自定义组件的实现

又是一些无趣的逻辑处理。在这里就不贴流程了。v-model 在自定义组件的特点是“所在的子组件还能指定哪个属性和哪个事件”:

{
  model: {
    prop: 'msg',
    event: 'change'
  }
}

无非就是执行到 transformmodel的时候: (也就是在 createComponent的时候)

function transformModel (options, data) {
  var prop = (options.model && options.model.prop) || 'value';
  var event = (options.model && options.model.event) || 'input'
  // ......
}
文章目录
  1. 双向绑定:还是要依赖 数据劫持 来实现
  2. 先来总结一下v-model的特点
  3. v-model 在控件的实现
    1. v-model还是和单纯“value + @input”有区别,比如中文打字到一半还没按空格,v-model不会获取到,而后者会做“预输入延迟更新”,即延迟触发input
  • v-model 在自定义组件的实现