v-model 指令
首先需要理解,v-model 本质上是语法糖,在代码背后,模板编译器会对 v-model 进行更冗长的等价展开。
形如
<input v-model="searchText" />
等价于
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
所以 v-model 做的事情就是绑定一个响应式变量,并监听一个事件用来更新这个变量的值,因而 v-model 在使用上会有一些限制:
-
限制:
<input>、<textarea><select><checkbox>、<radio>- components
-
修饰符:
-
用法:
在表单控件或者组件上创建双向绑定。
表单控件上可以使用
v-model指令在表单<input>、<textarea>及<select>等元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。因为v-model本质上不过是语法糖,v-model在内部为不同的输入元素使用不同的 property 并抛出不同的事件:- text 和 textarea 元素使用
valueproperty 和input事件; - checkbox 和 radio 使用
checkedproperty 和change事件; - select 字段将
value作为 prop 并将change作为事件。
在组件上的使用稍有不同
- text 和 textarea 元素使用
v-model 在 Vue2 中的使用
在 Vue 2.0+ 的版本中,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像自定义单选框、复选框等类型的封装输入控件可能会将 value attribute 用于不同的目的。为了解决这个问题,Vue 在 Vue 2.2 中引入了 model 选项,可以自定义要接受的属性名和自定义事件名:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
,
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
组件上还是这样使用
<base-checkbox v-model="isChecked"></base-checkbox>
v-model 在 Vue3 中的使用
Vue2.x 中因为 v-model 默认的编译展开为 value 的 prop 和 input 事件可能会发生冲突,那么可不可以直接使用另外的属性和方法呢?其实 Vue3 中就实现了这个功能,v-model绑定的不再是value,而是modelValue,接收的方法也不再是input,而是update:modelValue。
当使用在一个组件上时,v-model 会被展开为如下形式:
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
<CustomInput> 组件内部则需要做两件事:
- 将内部原生
<input>元素的valueattribute 绑定到modelValueprop - 当原生的
input事件触发时,触发一个携带了新值的update:modelValue自定义事件
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
组件上的使用方式还是没变:
<CustomInput v-model="searchText" />
并且 Vue3 中的 v-model 指令还能支持参数和多个绑定
v-model 支持参数
默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:
<MyComponent v-model:title="bookTitle" />
在这个例子中,子组件应声明一个 title prop,并通过触发 update:title 事件更新父组件值:
<!-- MyComponent.vue -->
<script>
export default {
props: ['title'],
emits: ['update:title']
}
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
v-model 支持多个绑定
Vue3 支持在单个组件实例上创建多个 v-model 双向绑定。组件上的每一个 v-model 都会同步不同的 prop,而无需额外的选项:
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>
<script>
export default {
props: {
firstName: String,
lastName: String
},
emits: ['update:firstName', 'update:lastName']
}
</script>
<template>
<input
type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"
/>
<input
type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"
/>
</template>