不论在vue2和vue3当中,v-model指令都是使用的相当多的,其不过是Vue语法糖中的一种。
当我们在Vue2中input标签中使用v-model指令
<input type="text" v-model="name" />
相当于
<input type="text" :value="name" @input="name=$event.target.value" >
在input标签中使用v-model,其根本是将name绑定到value属性上,并监听input事件,一旦监听到input事件,就执行语句 name = $event.target.value。
对于其他标签,Vue绑定不同的属性并监听不同的事件。
v-model在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用
valueproperty 和input事件;- checkbox 和 radio 使用
checkedproperty 和change事件;- select 字段将
value作为 prop 并将change作为事件。
当我们想要将v-model使用在自定义的组件上时:
<self-input v-model="name" />
如果没有进行相关的配置,其会默认使用名为value的prop,并监听名为input的事件,在监听的事件中执行语句value=$event,就像如下这样。
<self-input :value="name" $input="name=$event" >
这样一来,在实际编写代码中,我们可以编写一个组件,如果想要在其上使用v-model指令,则我们在编写该组件的时候,需要一个名为value的prop,并在需要更改的时候,emit一个名为input事件,并同时携带参数$event,即新值。但千篇一律的value和input既不符合规范,也不优雅。
于是乎,就有了model选项,指定v-model所要绑定的prop以及事件名。
Vue.component("self-input",{
props:["name"],
model:{
prop:"name", // 指定v-model绑定的prop为name
event:'changeName' // 指定v-model所监听的事件名,当监听到该事件时,就执行赋值语句,实现双向绑定
},
template:`
<input :value="name" @input="$emit("changeName",name)">
`
})
在组件中的input标签中,不能这样写, ,因为 <input v-model="name"/>name 是该组件的prop,不能在组件中进行修改。
但是,配合计算属性,我们仍然可以在组件中的input标签中使用v-model指令。
Vue.component("self-input",{
props:["name"],
model:{
prop:"name",
event:"changeName",
},
computed:{
nickname:{
get(){
return this.name;
},
set(newValue){
this.$emit("changeName",newValue);
}
}
},
template:`
<input type="text" v-model="nickname" />
`
})
当我们在Vue3中使用v-model指令,如果使用在input等html标签上,则与vue2无差别,如果是使用在自定义的组件之上,如:
<self-input v-mode="name" />
则相当于:
<self-input :model-value="name" @update:mode-value="name=$event">
在vue3中,v-model绑定的默认prop与事件名发生了变化,默认prop为model-value,默认的事件名是update:model-value。我们可以通过传递参数来改变prop。如:
<self-input v-model:name="name" />
这时v-model绑定的prop为name,同时监听的事件名发生了变化,为update:name。
在vue3中,我们可以理解v-model的默认参数是model-value ,通过设置不同的参数,那么我们就可以在v组件中使用多个v-model。详情请查看vue3的官方文档.