Vue 官網(wǎng)教程上關(guān)于 v-model
的講解不是十分的詳細(xì)靡挥,寫這篇文章的目的就是詳細(xì)的剖析一下, 并介紹 Vue 2.2 v-model
改進(jìn)的地方舵匾,然后穿插的再說(shuō)點(diǎn) Vue 的小知識(shí)哟绊。
在 Vue 中湿右,有許多方法和 Angular 相似,這主要是因?yàn)?Angular 是 Vue 早期開(kāi)發(fā)的靈感來(lái)源芜抒。然而珍策,Augular 中存在許多問(wèn)題,在 Vue 中已經(jīng)得到解決宅倒。
v-model 用在 input 元素上時(shí)
v-model
雖然很像使用了雙向數(shù)據(jù)綁定的 Angular 的 ng-model
攘宙,但是 Vue 是單項(xiàng)數(shù)據(jù)流,v-model
只是語(yǔ)法糖而已:↓
<input v-model="sth" />
<input :value="sth" @input="sth = $event.target.value" />
第一行的代碼其實(shí)只是第二行的語(yǔ)法糖拐迁,兩行代碼是等價(jià)的蹭劈。
要理解這行代碼,首先你要知道 input
元素本身有個(gè) oninput 事件线召,這是 HTML5 新增加的铺韧,類似 onchange
,每當(dāng)輸入框內(nèi)容發(fā)生變化缓淹,就會(huì)觸發(fā) oninput
哈打,把最新的value
賦值給 sth
變量。
如果你不知道 $event 是從哪來(lái)的讯壶,那你需要點(diǎn)擊它再?gòu)?fù)習(xí)一下文檔料仗。
我們仔細(xì)觀察語(yǔ)法糖和原始語(yǔ)法那兩行代碼,可以得出一個(gè)結(jié)論:
在給 <input /> 元素添加 v-model 屬性時(shí)伏蚊,默認(rèn)會(huì)把 value
作為元素的屬性立轧,把 input
事件作為實(shí)時(shí)傳遞 value 的觸發(fā)事件
(理解上面那句話非常重要,如果沒(méi)有理解躏吊,務(wù)必再把上面的內(nèi)容多看兩遍氛改,多想想,直到理解為止)
當(dāng) v-model 用在組件上時(shí)
v-model
不僅僅能在 input
HTML 原生標(biāo)簽上用颜阐,在 vue 組件上也能使用平窘;下面是一個(gè)和 Vue 官網(wǎng)教程類似的例子:
父組件 price
的初始值是 100,子組件是一個(gè)輸入框凳怨;輸入框的值改變時(shí)瑰艘,能實(shí)時(shí)更新父組件的 price
// 父組件
<template>
<div id="demo">
<currency-input v-model="price"></currentcy-input>
<span>{{price}}</span>
</div>
</template>
<script>
export default {
data() {
return {
price: 100,
}
}
}
</script>
// 子組件 currency-input
<template>
<input
:value="value"
@input="$emit('input', $event.target.value)"
/>
<!--為什么這里把 'input' 作為觸發(fā)事件的事件名是鬼?`input` 在哪定義的?-->
</template>
<script>
export default {
props: {
value: String, // 為什么這里要定義 value 屬性紫新,父組件貌似沒(méi)有給子組件傳遞 value 熬邸?
}
}
</script>
注釋里列了兩個(gè)問(wèn)題芒率,如果你都知道答案囤耳,那么恭喜你真正掌握了 v-model
!
如果你沒(méi)明白,那么可以繼續(xù)往下看
我們對(duì)比下下面兩行代碼
<currency-input v-model="price"></currentcy-input>
<currency-input :value="price" @input="price = $event.target.value"></currency-input>
這兩行代碼實(shí)際上沒(méi)有任何區(qū)別偶芍,只不過(guò)第一行是第二行的語(yǔ)法糖而已充择!
現(xiàn)在你知道 value
和 input
從哪來(lái)的了吧。與上面總結(jié)的類似:
給組件添加 v-model
屬性時(shí)匪蟀,默認(rèn)會(huì)把value
作為組件的屬性椎麦,把 input
作為給組件綁定事件時(shí)的事件名
v-model 的缺點(diǎn)和解決辦法
v-model 應(yīng)用到組件上,會(huì)有一些體驗(yàn)不好的場(chǎng)景材彪。因?yàn)樗J(rèn)會(huì)把 value
作為組件的屬性观挎,把 input
作為給組件綁定事件時(shí)的事件名。
// 父組件
<my-button v-model="number"></my-button>
<script>
data() {
return {
number: 1,
}
}
</script>
// 子組件
<template>
<button @click="add">點(diǎn)擊按鈕自增 1</button>
</template>
<script>
export default {
props: {
value: Number, // 屬性名必須是 value
},
methods: {
add() {
this.$emit('input', this.value + 1) // 事件名必須是 input
},
}
}
</script>
有時(shí)間我們不想用 value
當(dāng)做默認(rèn)的屬性名段化,也不想把 input
當(dāng)做事件名嘁捷。能不能自定義呢?
在 Vue 2.2 及以上版本显熏,你可以在定義組件時(shí)通過(guò) model 選項(xiàng)的方式來(lái)定制 prop/event:↓
// 父組件
<my-button v-model="number"></my-button>
<script>
data() {
return {
number: 1,
}
}
</script>
// 子組件
<template>
<button @click="add">點(diǎn)擊按鈕自增 1</button>
</template>
<script>
export default {
model: {
prop: 'num', // 自定義屬性名
event: 'addNum' // 自定義事件名
},
props: {
num: Number,
},
methods: {
add() {
this.$emit('addNum', this.num + 1)
},
}
}
</script>
看到這里我相信你肯定理解了 Vue 的 v-model
雄嚣,文中如有錯(cuò)誤,歡迎在評(píng)論中指出佃延,謝謝现诀。
碼字辛苦,文章如對(duì)您有幫助履肃,麻煩支持點(diǎn)贊~