vue源码解读(四、v-model双向数据绑定)

v-model简介

v-model是Vue用于表单元素上创建双向数据绑定,它本质是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能。

实例代码

 
请输入:
你输入的是:

genDirectives

vue通过 genDirectives来初始化指令。

function genDirectives (el, state) {
  var dirs = el.directives;
  if (!dirs) { return }
  var res = 'directives:[';
  var hasRuntime = false;
  var i, l, dir, needRuntime;
  for (i = 0, l = dirs.length; i < l; i++) {
    dir = dirs[i];
    needRuntime = true;
    var gen = state.directives[dir.name];
    if (gen) {
      // compile-time directive that manipulates AST.
      // returns true if it also needs a runtime counterpart.
      needRuntime = !!gen(el, dir, state.warn);
    }
    if (needRuntime) {
      hasRuntime = true;
      res += "{name:\"" + (dir.name) + "\",rawName:\"" + (dir.rawName) + "\"" + (dir.value ? (",value:(" + (dir.value) + "),expression:" + (JSON.stringify(dir.value))) : '') + (dir.arg ? (",arg:" + (dir.isDynamicArg ? dir.arg : ("\"" + (dir.arg) + "\""))) : '') + (dir.modifiers ? (",modifiers:" + (JSON.stringify(dir.modifiers))) : '') + "},";
    }
  }
  if (hasRuntime) {
    return res.slice(0, -1) + ']'
  }
}

在genDirectives函数生成对应的为之后操作所需要得一些json数据。

genDefaultModel

在给页面上绑定了v-model之后,就会根据表单元素的tag标签以及type属性的值,去调用不同的model方法,这里我们调用genDefaultModel

  function genDefaultModel (
  el,
  value,
  modifiers
) {
  var type = el.attrsMap.type;

  // warn if v-bind:value conflicts with v-model
  // except for inputs with v-bind:type
  if (process.env.NODE_ENV !== 'production') {
    var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
    var typeBinding = el.attrsMap['v-bind:type'] || el.attrsMap[':type'];
    if (value$1 && !typeBinding) {
      var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
      warn$1(
        binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
        'because the latter already expands to a value binding internally',
        el.rawAttrsMap[binding]
      );
    }
  }

  var ref = modifiers || {};
  var lazy = ref.lazy;
  var number = ref.number;
  var trim = ref.trim;
  var needCompositionGuard = !lazy && type !== 'range';
  var event = lazy
    ? 'change'
    : type === 'range'
      ? RANGE_TOKEN
      : 'input';

  var valueExpression = '$event.target.value';
  if (trim) {
    valueExpression = "$event.target.value.trim()";
  }
  if (number) {
    valueExpression = "_n(" + valueExpression + ")";
  }

  var code = genAssignmentCode(value, valueExpression);
  if (needCompositionGuard) {
    code = "if($event.target.composing)return;" + code;
  }

  addProp(el, 'value', ("(" + value + ")"));
  addHandler(el, event, code, null, true);
  if (trim || number) {
    addHandler(el, 'blur', '$forceUpdate()');
  }
}

genDefaultModel先是去检测该表单元素是否同时有v-model绑定和v-bind:value。获取到表单元素的修饰符lazy(替换input的change时间),number(入字符串转为数字)及trim.(去除两边空格),之后生成值得表达式,通过genAssignmentCode()方法生成v-model value值得代码。根据本文的例子返回的结果就是"message=$event.target.value"。最后添加响应的事件和属性。

总结

请输入:
你输入的是:

这一句代码经过vue的处理之后,就变成了

相当于将data里面的值通过响应式更新到视图上,然后给input绑定change事件,在改变值得时候对data里面message值做修改并更新视图。

你可能感兴趣的:(vue源码解读(四、v-model双向数据绑定))