目录
Vue 2中的v-model
默认使用
自定义使用
修饰符.sync (Vue2)
Vue3.x 使用 v-model
vue 3 的v-model使用原理
多个 v-model 使用
总结
Vue 2中的v-model
在Vue 2中,v-model是一个用于在子组件和父组件之间双向绑定数据的指令。当在子组件中使用v-model时,它默认绑定到value
属性,并且在子组件中可以通过$emit('input', newValue)
来改变父组件的数据。这种双向绑定非常方便,但有时也可能引起状态管理上的混乱。
v-model 是语法糖,本质还是父子组件间的通信。父子组件通信时有两种方式:
- 父给子传值:通过 props
- 子给父传值:通过 Events up,使用 $emit 触发事件。
默认使用
在vue
中,v-model
的值相当于默认
传递了一个名为 value 的 prop
和一个名为 input 的方法
(注意,这个value
的prop
是需要在自定义组件内声明的),如下:
父组件
<template>
<custom-input v-model="message"></custom-input>
</template>
<script>
import CustomInput from './CustomInput.vue';
export default {
components: {
CustomInput,
},
data() {
return {
message: '',
};
},
};
</script>
子组件
在CustomInput
组件内部,你需要接收value
属性并在适当的时候触发input
事件,以保持与父组件的数据同步。这是CustomInput
组件的例子:
<template>
<input :value="value" @input="$emit('input', $event)">
</template>
<script>
export default {
props: ['value'],
};
</script>
这样,当在父组件中使用v-model="message"
时,CustomInput
组件将能够正确地与message
数据进行双向绑定。
至于原理,v-model
实际上是语法糖,它通过绑定value属性和监听input事件来实现双向数据绑定。当子组件的输入发生变化时,触发input事件,父组件监听到这个事件后更新相应的数据,从而实现数据的双向同步。
自定义使用
默认使用时,事件名input
和 prop名value
是固定的,如果需要修改,就需要在子组件使用 model
选项。如下:
父组件
使用model选项修改属性和事件名实现自➕1 等价于 :num + @change
<!-- 父组件 -->
<template>
<MyInput v-model="count" />
<!-- 等价于 -->
<MyInput :num="count" @change="count=$event" />
</template>
<script>
import MyInput from './components/MyInput.vue'
export default {
components: { MyInput },
data() {
return {
count: 1
}
}
}
</script>
子组件
利用model 选项 修改 props 跟event 完成自定义
<!-- 子组件 -->
<template>
<div>
<span>{{num}}</span>
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
name: 'MyInput',
model: {
prop: 'num', // 将默认value属性改为num
event: 'change' // 将默认input事件改为change
}
props: {
num: {
type: Number,
default: 0
}
},
methods: {
add() {
this.$emit('change', this.num+1)
}
}
}
</script>
修饰符.sync (Vue2)
.sync的作用
实现父子组件数据之间的双向绑定, 与 v-model 类似.
区别: 在 Vue2中 一个组件上只能有一个v-model, 而 .sync 修饰符可以有很多个.
.sync修饰符的原理
// 正常父传子:
<com1 :a="num" :b="num2"></com1>
// 加上sync之后父传子:
<com1 :a.sync="num" .b.sync="num2"></com1>
// 它等价于
<com1
:a="num" @update:a="val=>num=val"
:b="num2" @update:b="val=>num2=val"></com1>
// 相当于多了一个事件监听,事件名是update:a,回调函数中,会把接收到的值赋值给属性绑定的数据项中。
.sync 与 v-model 区别是
相同点: 都是语法糖, 都是可以实现父子组件中的数据的双向通信
区别点:
- 格式不同: v-model="num" , :num.sync="num"
- v-model : @input + value
- :num.sync: @update:num
- v-model只能用一次; .sync 可以有多个
Vue3.x 使用 v-model
在Vue 3中,v-model引入了一些重要的改进,使其更具可定制性和可扩展性。以下是其中一些重要的改进:
vue 3 的v-model使用原理
v-model 默认绑定的属性名为:modelValue
v-model 默认绑定的事件名为:update:modelValue
// 所以我们需要使用 modelValue 和 update:modelValue 来接收
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
我们可以自定义 v-model 绑定的名称
父组件
// 父组件
<template>
<son-component v-model:msg='msg'></son-component> // 使用 v-model:name 来自定义名称
</template>
子组件
// 子组件
export default {
props: ['msg'],
emits: ['update:msg']
}
单个数据双向绑定完整示例
//父组件代码
<child-comp v-model="name" />
子组件代码:
<template>
<input type="text" v-model="newValue">
</template>
<script>
export default {
props:{
modelValue:{
type:String,
default:''
}
},
computed:{
newValue:{
get:function(){
return this.modelValue
},
set:function(value){
this.$emit('update:modelValue',value)
}
}
}
}
</script>
注意:以上是 Vue3 中接收 v-model 的方法, Vue2 需要使用 model 来接收
vue3 使用特定的 modelValue ,避免 value 的占用,通过 update:modelValue 实现数据双向绑定。值得注意的是,vue3 移除了 model 选项。
多个 v-model 使用
在 vue3 一个组件可以使用多个 v-model ,统一了 vue2 的 v-model 和 .sync 修饰符。
<child-comp v-model:name="name" v-model:age="age" />
//可翻译为
<child-comp
:name="name" @update:name="name=$event"
:age="age" @update:age="age=$event" />
实现多个数据双向绑定完整实例:
//父组件代码
<child-comp v-model:name="name" v-model:age="age" />
//子组件代码
<template>
<div>
<input type="text" v-model="newName">
<input type="text" v-model="newAge">
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:''
},
age:{
type:String,
default:""
}
},
emits:['update:name','update:age'],
computed:{
newName:{
get:function(){
return this.name
},
set:function(value){
this.$emit('update:name',value)
}
},
newAge:{
get:function(){
return this.age
},
set:function(value){
this.$emit('update:age',value)
}
}
}
}
</script>
总结
从 vue2.0 开始,组件上自定义 v-model 进行数据双向绑定,不断改进它的使用。过程如下
<child-comp v-model="msg" />
vue2.0 可以翻译为:
<child-comp :value="msg" @input="msg=$event" />
存在问题:v-model 和 value 有一个强绑定关系,如果子组件中有一个 input 原生标签,此时就会影响原生标签的 value 和 input 事件
vue2.2版本
引入了 model 组件选项,允许开发者任意指定 v-model 的 props 和 event 。这样就解决了 vue2.0 中的 v-model 和 value 的强绑定关系。但是还是存在一个问题,就是多个数据双向绑定时,还是需要借助 .sync 修饰符。
vue3.x 版本
Vue3 可以翻译为:
<child-comp :modelValue="msg" @update:modelValue="msg=$event" />
vue3 统一 使用 v-model 进行多个数据双向绑定,废除了 model 组件选项。