v-model 原理
一句话来说就是 v-model 是一个语法糖。会生成 value 属性和 input 事件。
当 v-model 使用在表单元素上时,会根据元素的不同而采用不同的处理:
- 当
<input type="text">
文本 和<textarea>
上使用时,会默认给元素绑定名为value
的属性和名为input
的事件; - 当
<input type="checkbox">
复选框 和<input type="radio">
单选框 上使用时,会默认绑定名为checked
的 属性 和名为change
的事件; - 当
<select>
选择框 上使用时,则绑定名为value
的 属性 和名为change
的事件。
v-model 还可以作用在自定义组件。默认也会生成一个 value 属性和 input 事件。
<!-- MyInput 组件代码 -->
<template>
<div>
<input type="text" :value="value" @input="$emit('input',$event.target.value)">
</div>
</template>
<script>
export default {
props: {
value: String, // 默认接收一个名为 value 的 prop
}
}
</script>
上面代码就实现了组件的 v-model 功能,当在这个组件上使用 v-model 时:
<my-input v-model="msg"></my-input>
其实就等同于:
<my-input :value="msg" @input="msg = $event">
Vue 还提供了 model 选项,用于将属性或事件名称改为其他名称,比如上面的 MyInput 组件,我们改一下:
<template>
<div>
<input
type="text"
:value="title"
@input="$emit('change', $event.target.value)"
/>
</div>
</template>
<script>
export default {
model: {
prop: "title", // 将默认的 prop 名 value 改为 title
event: "change", // 将默认的事件名 input 改为 change
},
props: {
title: String, // 注意 template 代码中也要修改为 title
},
};
</script>
此时使用组件:
<my-input v-model="msg"></my-input>
// 等同于
<my-input :title="msg" @change="msg = $event"></my-input>
sync 修饰符
还是拿上面的 MyInput 说明,我们还是传入一个 title 的 prop,同时组件内部抛出 update:title 事件,代码如下:
// MyInput 组件中,修改抛出的事件名为 update:title
<input type="text" :value="title" @input="$emit('update:title', $event.target.value)" />
此时如果使用这个组件,正常应该是这样:
<my-input :title="msg" @update:title="msg = $event"></my-input>
但此时可以使用 .sync 修饰符来简化:
<my-input :title.sync="msg"></my-input>
可以看到 .sync 和 v-model 所能达到的效果是一样的,应用场景:封装弹框类的基础组件, visible属性 true显示 false隐藏。