Vue3 05.内置指令3 v-model
v-model
在表单输入元素或者组件上创建双向绑定。
表单输入绑定
在前端处理表单时,我们常常需要将表单输入框的内容同步给代码中的变量。如果手动操作的话可能会比较麻烦。
<input |
v-model
指令帮我们简化了这一操作:
<input v-model="text" /> |
v-model
可以用于多种不同类型的输入,<textarea>
、<select>
元素。它会根据所使用的元素自动使用对应的DOM属性和事件结合。
- 文本类型的
<input>
和<textarea>
元素会绑定value
property并监听input
事件。<input type="checkbox">
和<input type="radio">
会绑定checked
property并监听change
事件。<select>
会绑定value
property并监听change
事件。
v-model
会忽略任何表单元素上初始的value
、checked
或selected
attribute。它始终将当前绑定的变量值视为数据的正确来源。
修饰符
.lazy
默认情况下,v-model
会在每次input
事件之后更新数据(IME拼字阶段的状态除外)。可以通过添加lazy
修饰符来改为每次change
事件后更新数据。
<!-- 在"change"事件后同步更新而不是"input" --> |
.number
如果想要在输入后自动将输入的内容转为数字,可以在v-model
后添加.number
修饰符来管理输入:
<input v-model.number="age" /> |
如果该值无法被parseFloat()
函数处理,那么将返回原始值。number
修饰符会在输入框有type="number"
时自动启用。
.trim
如果想要默认自动去除用户输入内容两端的空格,可以在v-model
后添加.trim
修饰符:
<input v-model.trim="msg" /> |
组件v-model
v-model
可以在组件上使用以实现双向绑定。从Vue3.4开始,推荐实现方式是使用defineModel()
宏。
<!-- Child.vue --> |
父组件可以用v-model
绑定一个值:
<!-- Parent.vue --> |
defineModel()
返回的值是一个ref,它可以像其他ref一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用:
- 它的
.value
和父组件的v-model
的值同步。 - 当它被子组件变更了,会触发父组件绑定的值一起更新。
这意味着也可以用
v-model
把这个ref绑定到一个原生input元素上,在提供相同v-model
用法的同时轻松包装原生input元素。
底层机制
defineModel
内部做了两件事:
- 一个名为
modelValue
的prop,本地ref的值与其同步; - 一个名为
update:modelValue
的事件,当本地ref的值发生变更时触发。
举个例子:
<!-- Child.vue --> |
然后在父组件中
<!-- Parent.vue --> |
由此可见非常冗长,虽然这样写容易理解底层机制。
因为defineModel
声明了一个prop,可以通过传递选项,来声明底层prop的选项:
// 使 v-model 必填 |
注意点,如果给
defineModel
设置了一个默认值且在父组件中没有给该prop提供任何值,会导致父子组件之间不同步。
v-model
的参数
组件上的v-model
也可以接受一个参数:
<my-component v-model:title="bookTitle" /> |
在子组件中,可以通过将字符串作为第一个参数传递给defineModel()
来支持相应的参数:
<!-- MyComponent.vue --> |
如果需要额外的prop选项,应该在model名称之后传递:
const title = defineModel('title', { required: true }) |
多个v-model
绑定
利用v-model的参数
可以指定参数的功能,可以在单个组件实例上创建多个v-model
双向绑定。
组件上的每一个v-model
都会同步不同的prop,而无需额外的选项:
<user-name |
<script setup> |
处理v-model
修饰符
在某些场景下,可能需要一个自定义组件的v-model
支持自定义的修饰符。
比如,创建一个自定义的修饰符capitalize
,它会自动将v-model
绑定输入的字符串值第一个字母转为大写:
<my-component v-model.capitalize="myText" /> |
通过像这样解构defineModel()
的返回值,可以在子组件访问添加到组件v-model
的修饰符:
<script setup> |
为了能够基于修饰符选择性地调节值的读取和写入方式,我们可以给defineModel()
传入get
和set
这两个选项。这两个选项在从模型引用中读取或设置值时会接收到当前的值,并且它们都应该返回一个经过处理的新值。
<script setup> |