笔者最近在项目中发现,不管是前端组件库或者公司自己封装的组件,表单大多使用v-model绑定,所以在此整理一下相关知识。
v-model是什么
官网上说只是一个语法糖,默认情况下,一个组件的 v-model 会使用 value 属性和 input 事件:
<input v-model="value" />
// 等价
<input
v-bind:value="value"
v-on:input="value = arguments[0]"
/>
这又引发另一个问题,诸如单选框、复选框之类的输入类型可能把 value 属性用作了别的目的(select用selected,checkbox用checked)。修改如下:
// 父组件
<a-select v-model="value" />
// 等价
<a-select
v-bind:selected="selected"
v-on:change="selected = arguments[0]"
/>
// 子组件中
<select
:value="selected"
@change="(e) => $emit('change', e.target.value)"
>
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
export default() {
model: {
prop: 'selected',
event: 'change'
},
props: {
selected: {
type: String
}
}
}
注:
父组件里面v-model相当于使用selected属性和change事件了,对应子组件中model的prop和event。
父组件既然用selected传值,子组件中props当然用selected接收。父组件监听的change事件,子组件中用$emit派发change事件。
当然子组件中model不是必须要重写v-model,只要我们props里面接收value和$emit派发input事件,v-model指令就能成立。
vue3中的v-model变化
vue3中一个组件可以绑定多个v-model,其实就是.sync修饰符的语法改变了个名称。
v-model:first-name=“firstName”
$emit(‘update:firstName’, $event.target.value)
vue2中我们写一个属性双向绑定时,不想写过多代码直接用sync修饰符:
// 父组件
<my-component :name.sync="name" />
// 等价
<my-component :name="name" @update:name="name = arguments[0]"/>
// 子组件
props: {
name: [String]
},
methods: {
handle() {
this.$emit('update:name', value)
}
}