官方文檔講的比較模糊,自己通過(guò)例子進(jìn)行理解煮岁。
v-model是語(yǔ)法糖
首先明確一點(diǎn),v-model僅僅是語(yǔ)法糖。
<input
type="text"
v-model="something">
<!--等價(jià)于-->
<input
type="text"
v-bind:value="something"
v-on:input="something = $event.target.value">
還要理解$emit的用法:
vm.$emit(event,[...args])
觸發(fā)當(dāng)前實(shí)例上的事件匠楚。附加參數(shù)都會(huì)傳給監(jiān)聽器回調(diào)。
v-model在 普通input上
一定要明確在給 <input /> 元素添加 v-model 屬性時(shí)厂财,默認(rèn)會(huì)把 value 作為元素的屬性芋簿,然后把 'input' 事件作為實(shí)時(shí)傳遞 value 的觸發(fā)事件(具體參考語(yǔ)法糖的解釋)
v-model用在組件上
這里是一個(gè)自定義組件currency-input,父組件的 price 的初始值是 100,更改子組件的值能實(shí)時(shí)更新父組件的 price
html:
<div id="demo">
<currency-input v-model="price"></currentcy-input>
<span>{{price}}</span>
</div>
js:
Vue.component('currency-input', {
template: `
<span>
<input
ref="input"
:value="value"
<!--為什么這里把 'input' 作為觸發(fā)事件的事件名璃饱?`input` 在哪定義的与斤?-->
@input="$emit('input', $event.target.value)"
>
</span>
`,
props: ['value'],// 為什么這里要用 value 屬性,value在哪里定義的荚恶?貌似沒找到傲么?
})
var demo = new Vue({
el: '#demo',
data: {
price: 100,
}
})
這里的js代碼谒撼,props中接受了value食寡,但是在組件中<currency-input v-model="price"></currentcy-input>
并沒有傳入value,而且在input中是監(jiān)聽了input事件廓潜,但是并沒有在父組件中定義input抵皱。
要理解這個(gè),就要回到語(yǔ)法糖的問(wèn)題上茉帅,
<currency-input v-model="price"></currentcy-input>
本質(zhì)上等價(jià)于:
<currency-input :value="price" @input="price = arguments[0]"></currency-input>
所以可以看到value和input了
理解v-model在組件中的實(shí)現(xiàn)叨叙,給組件添加 v-model 屬性時(shí),默認(rèn)會(huì)把 value 作為組件的屬性堪澎,然后把 'input' 值作為給組件綁定事件時(shí)的事件名
代碼分析
所以這里在js中@input="$emit('input', $event.target.value)"
子組件在監(jiān)聽input事件發(fā)生的時(shí)候(即@input),向父組件傳遞了input($emit中的input)事件擂错,并且傳遞了當(dāng)前子組件的price值。
而在父組件中樱蛤,監(jiān)聽了自定義事件input钮呀,當(dāng)自定義事件input觸發(fā)后剑鞍,將當(dāng)前父組件自身的price值改為子組件中$emit上來(lái)的值($event.target.value 是作為$emit傳遞的參數(shù),所以是arguments[0])
v-model存在的問(wèn)題
對(duì)于復(fù)選框或者單選框的常見組件時(shí)爽醋,由于v-model默認(rèn)傳的是value蚁署,不是checked,觸發(fā)事件也不是oninput而是onchange
- 對(duì)于單純的input type='checkbox'
<input type="checkbox" :checked="status" @change="status = $event.target.checked" />
- 當(dāng)用到組件上時(shí):
<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'],
})
這個(gè)時(shí)候需要Vue的model選項(xiàng)
model選項(xiàng)可以指定當(dāng)前的事件類型和傳入的props
所以可以通過(guò)這么改進(jìn):
<my-checkbox v-model="foo"></my-checkbox>
Vue.component('my-checkbox', {
tempalte: `<input
type="checkbox"
<!--這里就不用 input 了蚂四,而是 balabala-->
@change="$emit('balabala', $event.target.checked)"
:checked="value"
/>`
props: ['checked'], //這里就不用 value 了光戈,而是 checked
model: { // model選項(xiàng)來(lái)指定
prop: 'checked',
event: 'balabala'
},
})