Vue指令 v-model详解
前言在一次的学习过程中,偶然发现v-model的一个“奇怪”使用方法,如下图:描述:在一个组件中,引入一个自定义组件input.vue。然后需要在父组件中操作input的输入框内容。父组件(index.vue)的子组件实例上定义了v-model;input.vue组件中定义一个props,有一个value值,另外input标签的input事件绑定了一个事件名为input 的 $emit。...
前言
在一次的学习过程中,偶然发现v-model的一个“奇怪”使用方法,如下图:
描述:
在一个组件中,引入一个自定义组件input.vue。然后需要在父组件中操作input的输入框内容。父组件(index.vue)的子组件实例上定义了v-model;input.vue组件中定义一个props,有一个value值,另外input标签的input事件绑定了一个事件名为input 的 $emit。
此示例中,我一直没有明白的地方有:
- 父组件(index.vue)中input实例上的v-model如何响应?
- 子组件(input.vue)中的props从哪里接受数据?
- input标签的input事件中 $emit 在哪里监听?
因此下决心搞清楚v-model指令
表单输入框双向数据绑定
起初,v-model的作用是对应表单<input>、<textarea> 及 <select> 元素上创建双向数据绑定。Vue官方文档明确表示:
但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
那么实现原理如下
<template>
<div class="hello">
<h4>首先测试普通input输入框: {{text}}</h4>
<input type="text" v-model="text"/>
<input type="text" @input="val = $event.target.value" :value="val">
<label>{{val}}</label>
</div>
</template>
<script>
export default {
name: 'index',
data () {
return {
text: '',
val: '112'
}
},
components: {
WInput
}
}
</script>
组件中有两个input,一个使用v-model,另一个就是双向数据绑定的实际原理,使用input标签的input事件做实时监听。
刚刚的示例是基于input标签实现的,那么如果是其他的表单标签呢:
v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
示例如下:
<template>
<div class="test">
<div class="radio-group">
<input type="radio" name="test" v-model="redioModel" value="one">
<input type="radio" name="test" @change="redioChange" value="two">
</div>
<div class="checkbox-group">
<input type="checkbox" value="1" v-model="checkboxVal">
<input type="checkbox" value="2" v-model="checkboxVal">
<input type="checkbox" value="3" @change="checkboxChange">
</div>
<div class="select-box">
<!-- 使用 @change="selectChange" 替代v-model效果一样-->
<select id="select" v-model="selectVal">
<option value>请选择</option>
<option value="1">test1</option>
<option value="2">test2</option>
<option value="3">test3</option>
<option value="4">test4</option>
</select>
</div>
</div>
</template>
<script>
export default {
name: 'test',
data () {
return {
redioModel: '',
checkboxVal: [],
selectVal: ''
}
},
watch: {
redioModel (newVal) {
console.log(newVal)
},
checkboxVal (newVal) {
console.log(newVal)
},
selectVal (newVal) {
console.log(newVal)
}
},
methods: {
/**
* radio v-modal等同事件
*/
redioChange (e) {
this.redioModel = e.target.value
},
/**
* checkbox v-model等同事件
*/
checkboxChange (e) {
const checked = e.target.checked
if (checked) {
this.checkboxVal.push(e.target.value)
} else {
const index = this.checkboxVal.findIndex(
item => item === e.target.value
)
this.checkboxVal.splice(index, 1)
}
},
selectChange (e) {
this.selectVal = e.target.value
}
}
}
</script>
单选框radio、复选框CheckBox、下拉窗select,其中都是用了v-modal 和事件change两种实现双重绑定的方式。效果相同。
自定义组件的 v-model
这是Vue2.2的新增,官方解释:
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突
这句定义已经很好地解释了文章一开始提出的疑问
意思就是在自定义组件上使用v-modal就相当于:
<template>
<div class="hello">
<h4>首先测试普通input输入框: {{text}}</h4>
<w-input v-model="text"/>
<!-- 上行等价于下行 -->
<w-input @input="value => val = value" :value="val"/>
<label>{{val}}</label>
</div>
</template>
<script>
import WInput from './input'
export default {
name: 'index',
data () {
return {
text: '',
val: '123'
}
},
同理:
对于自定义组件中不同的响应的输出元素,也应该对应的抛出不同事件(同上):
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
// index.vue
<template>
<div class="hello">
<w-input v-model="changes"/>
<h4>测试选中: {{changes ? '选中': '未选中'}}</h4>
</div>
</template>
<script>
import WInput from './input'
export default {
name: 'index',
data () {
return {
changes: true
}
}
.....
// input.vue
<template>
<input type="checkbox" :checked="value" @change="handleInput">
</template>
<script>
export default {
name: 'w-input',
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
handleInput (e) {
this.$emit('input', e.target.checked)
}
}
}
总结
很多时候看Vue文档,对立面的一些方法属性,知其然不知其所以然,定义说的比较模糊,也不知道实际作用,应该怎么用,用在什么地方。只有不断地写项目,不断地尝试新的东西,才能活学活用
更多推荐
所有评论(0)