目录
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属性改为numevent: '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 组件选项。