Vue----v-model源码分析实现(表单元素部分)

前言

在很多时候我们说道vue,都说vue是双向绑定来实现的,但这么说是不太准确的,vue其实是mvvm数据驱动视图,用数据来驱动视图,DOM的改变。而v-model可以说是vue对于双向绑定的一个语法糖,那接下来看看v-model的实现吧。

编译

在把我们传入的模板编译成AST树的阶段,并不会对v-model做过多的处理,而是直接将其放在AST节点的directives中,而对v-model的处理是在我们生成render函数的codegen阶段。

codegen

在生成代码的这个阶段,在genElement这个函数中
在这里插入图片描述
从这里可以看到他会对我们的子节点在进行一次遍历,然后在进行一次genElement函数,当我们的节点含有v-model这个指令的时候,会命中genData$2这个函数,进入这个函数对我们的v-model进行一些处理。
在这里插入图片描述
在genData中会执行genDirectives这个方法,对我们的指令进行一些处理,而v-model就是指令之一。所以进入这个方法一看。
在这里插入图片描述
他会遍历当中的directives然后对我们遍历的每一个directive进行相应的处理,编译成一个res的形式。
而在!!gen(el, dir, state.warn)这个函数中,他会去执行model这个函数。那我们看看model这个函数的实现。
在这里插入图片描述
也是一对判断逻辑,对我们model的一些场景进行一些判断,我们写的是简单的v-model的例子,所以他会直接进入genDefaultModel这个函数当中,我们进入这个函数看看model的处理。
在这里插入图片描述
前面是对我们v-model指令的一些属性的判断,我们是没有加lazy或者number或者trim的,所以就会执行默认的addProp函数和addHandler函数,而这两个函数就是我们v-model实现的地方了。
在这里插入图片描述
上面是addProp函数的实现,很简单,他就是给我们的el元素去添加一个props属性,就是给input表单添加一个value的值。
而在addHandler中。

function addHandler (
  el,
  name,
  value,
  modifiers,
  important,
  warn,
  range,
  dynamic
) {
  modifiers = modifiers || emptyObject;
  // warn prevent and passive modifier
  /* istanbul ignore if */
  if (
    process.env.NODE_ENV !== 'production' && warn &&
    modifiers.prevent && modifiers.passive
  ) {
    warn(
      'passive and prevent can\'t be used together. ' +
      'Passive handler can\'t prevent default event.',
      range
    );
  }

  // normalize click.right and click.middle since they don't actually fire
  // this is technically browser-specific, but at least for now browsers are
  // the only target envs that have right/middle clicks.
  if (modifiers.right) {
    if (dynamic) {
      name = "(" + name + ")==='click'?'contextmenu':(" + name + ")";
    } else if (name === 'click') {
      name = 'contextmenu';
      delete modifiers.right;
    }
  } else if (modifiers.middle) {
    if (dynamic) {
      name = "(" + name + ")==='click'?'mouseup':(" + name + ")";
    } else if (name === 'click') {
      name = 'mouseup';
    }
  }

  // check capture modifier
  if (modifiers.capture) {
    delete modifiers.capture;
    name = prependModifierMarker('!', name, dynamic);
  }
  if (modifiers.once) {
    delete modifiers.once;
    name = prependModifierMarker('~', name, dynamic);
  }
  /* istanbul ignore if */
  if (modifiers.passive) {
    delete modifiers.passive;
    name = prependModifierMarker('&', name, dynamic);
  }

  var events;
  if (modifiers.native) {
    delete modifiers.native;
    events = el.nativeEvents || (el.nativeEvents = {});
  } else {
    events = el.events || (el.events = {});
  }

  var newHandler = rangeSetItem({ value: value.trim(), dynamic: dynamic }, range);
  if (modifiers !== emptyObject) {
    newHandler.modifiers = modifiers;
  }

  var handlers = events[name];
  /* istanbul ignore if */
  if (Array.isArray(handlers)) {
    important ? handlers.unshift(newHandler) : handlers.push(newHandler);
  } else if (handlers) {
    events[name] = important ? [newHandler, handlers] : [handlers, newHandler];
  } else {
    events[name] = newHandler;
  }

  el.plain = false;
}

他会对我们传入的handler事件进行一系列的判断,然后在把input事件绑定到v-model上。
所以对于我们的表单元素v-model的实现。其实就是一个语法糖,会给表单元素添加一个value的prop然后在添加一个input事件去监听我们的输入,然后再把值赋予value实现双向绑定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值