Vue语法糖之v-model

204 阅读2分钟

不论在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 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 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的官方文档.