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 屬性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM