目录
前言
用过Vue框架的都知道,v-model指令可以用来实现数据的双向绑定,在官方文档的介绍中也称其实v-model只不过是语法糖。v-model也常被当作面试题,如果只说用来实现数据双向绑定的语法糖只能说达到了解的程度,如果想在这道题上加分,这篇文章或许能够给你一些答案或灵感!
表单使用
v-model指令最常见的方式就是在表单元素上使用,实现绑定数据表单回显和修改表单数据同步的功能,简化代码逻辑,提高开发效率。
输入框
在输入框中使用v-model指令,等价于将数据绑定在value属性上,当input事件触发时,将事件目标元素的值重新赋给数据,textarea文本域同理。(其中$event是input事件抛出的参数,用来表示触发事件的dom元素实例)
- :value="绑定的数据"
- @input="绑定的数据 = 修改的值"
<input type="text" v-model="formData.name" />
等价于
<input type="text" :value="formData.name" @input="formData.name = $event.target.value"/>
扩展:还有一种常见的业务场景,如输入框失去焦点后进行延迟赋值(为了考虑性能进)。此时等价于使用change事件,在使用v-model指令时可携带一个修饰符lazy。
<input type="text" v-model.lazy="formData.account" />
等价于
<input type="text" :value="formData.account" @change="formData.account = $event.target.value"/>
单选框
在单选框使用v-model指令,将单选框类型的value绑定为v-model值,若匹配则为选中状态。
<input type="radio" v-model="formData.gender" value="male"> 男
<input type="radio" v-model="formData.gender" value="female"> 女
<input type="radio" v-model="formData.gender" value="other"> 其他
扩展:单选框一般用name属性来进行分组互斥,选中一个则不选其他。但此处没有使用name依然可以达到互斥的效果,是因为v-model绑定的属性,会寻找value的值进行匹配,当匹配上male时,female和other的状态会被刷新。
复选框
单复选框
我们经常会遇到使用复选框布尔值的业务,如“是否同意条款”、“是否同意协议”等,将复选框类型的v-model指令绑定数据即可。
<input type="checkbox" v-model="formData.notice"> 同意消息通知
注:此时的数据需定义为布尔值。
var formData = {
notice: false
};
组复选框
与单选框类似,除了v-model绑定数据外,还需定义value,用来匹配对应值。
<input type="checkbox" value="sing" v-model="formData.hobby"> 唱歌
<input type="checkbox" value="dance" v-model="formData.hobby"> 跳舞
<input type="checkbox" value="rap" v-model="formData.hobby"> Rap
<input type="checkbox" value="basketball" v-model="formData.hobby"> 篮球
注:此处的数据需定义为数组。
var formData = {
hobby: []
};
选择器
选择器是由select和option标签组合构成,使用v-model指令时需要在select标签中绑定数据,option中定义value。
<select v-model="formData.card">
<option value="">请选择</option>
<option value="idCard">身份证</option>
<option value="driveCard">驾照</option>
</select>
在组件中使用
v-model也可在组件中使用,设想如果我要实现一个上述所说的布尔值复选框,父组件要向自组件传入参数,当子组件修改后emit事件抛给父组件,父组件再处理对数据修改。
但这样父组件即要维护数据又要处理事件重新赋值,显得比较臃肿,我们希望父组件只维护数据即可。那么可以使用:value和@input结合的方式呢,也就是v-model指令。
父组件引入CheckBox组件是仅使用v-model来绑定数据,而不是使用传参+响应事件的方式去维护。
<CheckBox v-model="formData.notice"> 组件化的消息通知</CheckBox>
子组件可以根据v-model的原理,声明一个子组件私有的数据,初始化时赋值,私有数据变化时通知父组件,使用如下方式编写。
<template>
<div>
<input type="checkbox" v-model="checkVal" />
<slot></slot>
</div>
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default: false
}
},
data () {
return {
checkVal: false
}
},
created () {
this.checkVal = this.value
},
watch: {
value (val) {
this.checkVal = val
},
checkVal (val) {
this.$emit('input', val)
}
}
}
</script>
另外Vue给我们提供了一个能力,可以定制v-model的事件和数据,默认情况如下。
models: {
event: 'input',
prop: 'value'
},
总结
综上,v-model常用于表单和组件封装,在面试中如果可以描述一下数据双向绑定,语法糖永远是为了解决问题提升效率的,说一下v-bind:value和v-on:input这两种结合的方式;再说说都可应用于哪些场景,再说说封装组件中的使用会完整一些。
除此之外,随着前端现代UI框架的发展更替,在日常的工作中,表单不建议直接纯原生手写,建议使用UI框架,能够减少一些样式和兼容性的风险,从而提升效率。
以上代码的附件可查看本文绑定的资源(免费下载)。