vue-04双向绑定使⽤和原理

176 阅读2分钟
    1. vue中双向绑定是⼀个指令 v-model ,可以绑定⼀个响应式数据到视图,同时视图中变化能改变该值。
    1. v-model 是语法糖,默认情况下相当于 :value 和 @input 。使⽤ v-model 可以减少⼤量繁琐的事件处理代 码,提⾼开发效率。
    1. 通常在表单项上使⽤ v-model ,还可以在⾃定义组件上使⽤,表示某个值的输⼊和输出控制。

    1. 通过input v-model='xxx'的⽅式将xxx的值绑定到表单元素value上;
    • 对于checkbox,可以使⽤ true-value 和false-value指定特殊的值
    • 对于radio可以使⽤value指定特殊的值;
    • 对于select可以通过options元 素的value设置特殊的值;
    • 还可以结合.lazy,.number,.trim对v-mode的⾏为做进⼀步限定;
    • v-model ⽤在⾃ 定义组件上时⼜会有很⼤不同,vue3中它类似于 sync 修饰符,最终展开的结果是modelValue属性和 update:modelValue事件;vue3中我们甚⾄可以⽤参数形式指定多个不同的绑定,例如v-model:foo和vmodel:bar,⾮常强⼤!

    1. v-model 是⼀个指令,它的神奇魔法实际上是vue的编译器完成的。我做过测试,包含 v-model 的模板,转 换为渲染函数之后,实际上还是是value属性的绑定以及input事件监听,事件回调函数中会做相应变量更新操作。编译器根据表单元素的不同会展开不同的DOM属性和事件对,⽐如text类型的input和textarea会展开为 value和input事件;checkbox和radio类型的input会展开为checked和change事件;select⽤value作为属性,⽤change作为事件。

源码分析:vue2中的,模型绑定变成事件监听

//input: type=text
_c('input', { 
  directives: [{ name: "model", rawName: "v-model", value: (foo), expression: "foo" }], 
  attrs: { "type": "text" }, 
  domProps: { "value": (foo) }, 
  on: { 
    "input": function ($event) { 
      if ($event.target.composing) return; 
      foo = $event.target.value 
    } 
  } 
})
//input:type=checkbox
_c('input', { 
  directives: [{ name: "model", rawName: "v-model", value: (bar), expression: "bar" }], 
  attrs: { "type": "checkbox" }, 
  domProps: { "checked": Array.isArray(bar) ? _i(bar, null) > -1 : (bar) }, 
  on: { 
    "change": function ($event) { 
      var $$a = bar, $$el = $event.target, $$c = $$el.checked ? (true) : (false); 
      if (Array.isArray($$a)) { 
        var $$v = null, $$i = _i($$a, $$v); 
        if ($$el.checked) { 
          $$i < 0 && (bar = $$a.concat([$$v])) } 
        else { 
          $$i > -1 && (bar = $$a.slice(0, $$i).concat($$a.slice($$i + 1))) } } 
        else {
          bar = $$c
        } 
      } 
  } 
})
//select:
_c('select', { 
  directives: [{ name: "model", rawName: "v-model", value: (baz), expression: "baz" }], 
  on: { 
    "change": function ($event) { 
      var $$selectedVal = Array.prototype.filter.call( 
        $event.target.options, 
        function (o) { return o.selected } )
      .map( 
       function (o) { 
         var val = "_value" in o ? o._value : o.value; 
         return val } ); 
      baz = $event.target.multiple ? $$selectedVal : $$selectedVal[0]
    } 
  } 
}, [ 
  _c('option', { attrs: { "value": "vue" } }, [_v("vue")]), _v(" "),
  _c('option', { attrs: { "value": "react" } }, [_v("react")]) 
])

4、追问

    1. v-model 和 sync 修饰符有什么区别
    • 特别相似,分不大清楚,vue3就把sync合并到了v-model,之前sync就是用在自定义组件上的,v-model就是用在表单上的,现在直接合在一起了。
    1. ⾃定义组件使⽤ v-model 如果想要改变事件名或者属性名应该怎么做
    • vue2中使用的model选项,vue3中使用参数 属性用v-model:foo 事件用update:foo