既严肃认真,又生动活泼

Vue进阶——解析V-MODEL

最近重新过了一遍VUE官方文档,发现有些知识点官方解释的不是很清楚,所以在此深入解析一下,希望能帮到和我一样看文档遇到困惑的朋友们。

 

 

 

这里关于v-model,官方说明篇幅甚少,留下了一些疑问,下面详细解析v-model知识点。

 

 

一、v-model用在input上

v-model虽然很像使用了双向数据绑定的 Angular 的 ng-model,但是 Vue 是单项数据流v-model 只是语法糖而已:

 

// 最简形式,省略了value的显式绑定,省略了oninput的显式事件监听,是第二句代码的语法糖形式
<
input v-model="sth" />
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />

//第二句代码的简写形式 <input :value="sth" @input="sth = $event.target.value" />

 

首先你要知道 ,在HTML5新特性中,input 元素本身就有个 oninput 事件,类似 onchange ,每当输入框内容发生变化,就会触发 oninput ,把输入框最新的value值传递给 sth(第二句代码)。

关于$event,懂的朋友请忽略,$event知识点传送门

 

我们仔细观察语法糖和后两句完整版本代码,可以得出一个结论:

在给 <input /> 元素添加 v-model 属性时,默认会把 value 作为v-model的属性,默认把 'input' 事件作为实时传递 value 的触发事件,这就是官方文档这句话的意思:

 

二、v-model用在组件上

明白了v-model只是语法糖,它的默认值是value,默认监听事件是oninput,我们来看一个稍复杂的例子,它是将v-model使用在组件上。

 

类似于下图的效果,父组件的 price 的初始值是 100,更改子组件的值能实时更新父组件的 price

<div id="demo">
  <currency-input v-model="price"></currentcy-input>
  // 实际上是下列代码
  //<currency-input v-bind:value="price" v-on:input=" price = arguments[0] "></currency-input>
 <span>{{price}}</span> </div> <script> Vue.component('currency-input', { template: ` <span> <input :value="value" <!--这里之所以把 'input' 作为事件名向父级传递,正是因为非语法糖形式中v-on:input监听的是input事件--> @input="$emit('input', $event.target.value)" > </span> `, props: ['value'],// 这里的value正是被简写掉的,所以语法糖形式你找不到这个value在哪里绑定的,而在非语法糖形式找得到 }) var demo = new Vue({ el: '#demo', data: { price: 100, } }) </script>

现在你一定对于v-model是语法糖形式理解更深刻了,也对官方文档的困惑一点点明了了。

 

三、v-model的不足与解决方案

它的不足在官方文档也提出来了:

 

 

 我们来看看具体是什么意思。

在创建类似复选框或者单选框的常见组件时,v-model就不好用了。

<input type="checkbox" v-model="sth" />

v-model 给我们默认提供了 value 属性和 oninput 事件,但是在这里我们需要的不是 value 属性,而是 checked 属性,并且当你点击这个单选框的时候不会触发 oninput 事件,它只会触发 onchange 事件。这就是问题所在。

 

这是 v-model 只用在 input 上的情况,解决方案如下:

<input type="checkbox" :checked="status" @change="status = $event.target.checked" />

 

当v-model用在组件上时,解决方案如下:

<my-checkbox v-model="foo"></my-checkbox>

Vue.component('my-checkbox', {
  tempalte: `<input 
               type="checkbox"
               @change="$emit('input', $event.target.checked)"
               :checked="value"
             />`
  props: ['value'],
})

不明白的同学可以自己将语法糖形式写成完整的非语法糖形式,再结合前面的讲解进行分析。

 

四、在 Vue 2.2 版本,你可以在定义组件时通过 model 选项的方式来定制 prop/event:

 

//在这个组件中使用 v-model
<base-checkbox v-model="lovingVue"></base-checkbox>

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

 

lovingVue 的值就会传递给 checked prop。当 <base-checkbox> 内部触发一个 change 事件,并且传递一个新值,lovingVue 属性就会进行更新。

注意,仍然需要在组件 props 选项中声明 checked prop 属性。

 

posted @ 2018-05-29 11:48  大宝章  阅读(3753)  评论(0编辑  收藏  举报