Vue中的v-model
1.什么是v-model
v-model
是Vue框架的一种内置的API指令,本质是一种语法糖写法,它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。在Vue中,v-model
是用于在表单元素和组件之间创建双向数据绑定的指令。它可以简化表单元素的绑定,使得在用户输入时能够自动更新数据。
v-model
是value+input
的语法糖,是v-bind
和v-on
的简洁写法。v-model
就实现了双向数据绑定,实际上它就是通过Vue提供的事件机制。即在子组件通过$emit()
触发一个事件,在父组件使用v-model
即可。
2.什么是语法糖
在计算机科学中,语法糖(syntactic sugar)是指编程语言中可以更容易地表达一个操作的语法。它可以使程序员更加容易地使用这门语言,使操作变得更加清晰、方便,或者更加符合程序员的编程习惯。
具体来说,语法糖是语言中的一个构件,当去掉该构件后并不影响语言的功能和表达能力。例如,C语言中的标记a[i]
就是*(a+i)
的语法糖。
语言的处理器,包括编译器,静态分析器等,经常会在处理之前把语法糖构件转换成更加基础的构件,这个过程通常被称为"desugaring"。
简而言之,语法糖就是一种便捷写法。例如:input.map(a => a-8)
; 去掉语法糖就是:input.map(function (a) { return a - 8; })
; 通过例子你可以看出来,语法糖的使用其实就是让我们的写的代码更简单,看起来也更容易理解。
3.v-model常见的用法
单向数据绑定:
在Vue中,我们可以使用v-bind
实现单项的数据绑定,也就是通过父组件向子组件传入数据 ,但是反过来,子组件不可以修改父组件传递过来的数据 ,这也就是所谓的单向数据绑定。
双向数据绑定
v-bind
和v-on
实现了双向绑定实现了双向数据绑定。
3.1 输入框(input)
<input type="text" v-bind:value="value" v-on:input="value = $event.target.value" />
//或者
<input type="text" :value="value" @input="value = $event.target.value" />
v-model
是v-bind
和v-on
的语法糖,即,v-model
算是v-bind
和v-on
的简洁写法。
<input type="text" v-model="value" />
在这个例子中,v-model
将输入框的值与数据对象中的value
属性进行了绑定。当用户输入时,value
的值会自动更新。
3.2 复选框(checkbox)
<input v-model="checked" type="checkbox">
在这个例子中,v-model
将复选框的选中状态与数据对象中的checked
属性进行了绑定。当用户选中或取消选中复选框时,checked
的值会自动更新。
3.3 选择框(select)
<select v-model="selected">
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
在这个例子中,v-model
将选择框的值与数据对象中的selected
属性进行了绑定。当用户选择一个选项时,selected
的值会自动更新为所选选项的value值。
除了以上的例子,v-model
还可以用于其他表单元素和组件,如文本域(textarea)、开关(switch)等。它的工作原理是监听表单元素的输入事件,将输入值同步到绑定的数据属性上,同时当数据属性的值发生变化时,也会自动更新表单元素的值。
需要注意的是,v-model使用的数据属性通常应该是响应式对象或数组,这样才能够实现数据的双向绑定。如果使用非响应式对象或数组,v-model可能无法正常工作。
4.组件中的v-model
父组件:
<template>
<div>
<child-component v-model="message"></child-component>
<p>Message from parent component: {{ message }}</p>
</div>
</template>
<script>
import ChildComponent from './childComponent.vue';
export default {
data() {
return {
message: 'hello world'
};
},
components: {
ChildComponent
}
};
</script>
子组件:
<template>
<div>
<p>Message from parent component: {{ value }}</p>
<button type="button" @click="updateValue">更新</button>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ""
}
},
methods: {
updateValue() {
this.$emit("input", 'update message');
}
}
};
</script>
在这个例子中,父组件将message
属性绑定到子组件的value
属性上,并使用v-model
指令来实现双向数据绑定。子组件内部点击按钮更新message
,并使用$emit()
触发一个事件,从而更新父组件的message
属性。
由上可知:默认情况下,一个组件上的 v-model 会把value用作props且把 input用作event。
5.model选项
一些输入类型比如单选框和复选框按钮可能想使用value
、prop
来达到不同的目的。这时候可以使用 model 选项回避这些情况产生的冲突。
下面来看一个例子:在父组件展示一个子组件弹框,在子组件里面有关闭整个组件的功能。
- 之前:
我们是在子组件中通过$emit
触发父组件对应的方法,改变父组件上v-if
对应的变量来控制显示隐藏。 - 现在:
有了v-model
,这一切都变得很简单,最主要的是完全少了自定义对外暴露的关闭的方法,如果你关闭之后需要回调,那么通过监听你的是否显示的flag
即可,所以大可放心使用。
下面来看代码:
//父组件
<template>
<div id="app">
<HelloWorld v-model="showFlag" v-if="showFlag"></HelloWorld>
<button @click="showFlag=true">打开组件</button>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
data(){
return {
showFlag: false
}
},
components: {
HelloWorld
}
}
</script>
<template>
<div class="hello">
<h1>这是组件里面的内容</h1>
<button @click="close">关闭组件</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean
}
},
methods: {
close(){
this.$emit('change', false)
}
}
}
//对于子组件来说,允许自定义使用v-model时定制prop和event,
//v-model中的prop就是把value用作prop,input用作event,
//但是为了避免冲突,我们使用model的选项可以回避这些冲突,
//当然,你也得使用props声明checked这个prop。
6.vue2中v-model和vue3的v-model有什么区别?
用在组件上(vue2):
v-model
只能使用一次- 默认传递
value
属性,接受input
事件 - 默认传递的属性和事件可通过
model
选项进行修改
用在组件上(vue3):
v-model
只能使用一次,但可以在v-model后添加参数可使用多次- 默认传递
modelValue
属性(默认绑定的不是value
),接受update:modelValue
事件(接收的方法不是input
);当在v-model
后添加参数时如v-model:myPropName
,则传递为myPropName
属性,接受update:myPropName
事件 - 默认传递的属性和事件无法修改,必须是
modelValue
和update:modelValue
7.vue2中v-model和.sync修饰符的区别?
两者都是父子组件双向绑定的语法糖。vue3中去除了 .sync修饰符,但把相应功能合并到了 v-model 上,所以在 vue3 中,v-model 可以使用多次。
不同点:
v-model
背后是value
属性 和input
事件myPropName.sync
背后是myPropName
属性 和update:myPropName
事件- 在组件上
v-model
只可使用一次,.sync
可以有多个