v-modal是一个语法糖,我们直接看示例
<!-- 父组件 -->
<template>
<div>
<div>{{ inputVal }}</div>
<InputCom v-model="inputVal"/>
<!-- 同样可以写成下面的形式 -->
<!-- <InputCom :value="inputVal" @input="val => inputVal = val"/> -->
</div>
</template>
<script>
import InputCom from './InputCom';
export default {
components: { InputCom },
data() {
return {
inputVal: ''
}
}
}
</script>
<!-- 子组件 -->
<template>
<input :value="value" @input="$emit('input', $event.target.value)"/>
</template>
<script>
export default {
props: ['value']
}
</script>
从上面的示例我们可以看到,父组件通过 v-model 双向绑定了一个值:inputVal ;在子组件中就默认得到了一个名为 value 的 prop 和一个 input 方法,就可以监听 input 元素的 input 事件(我们一般用input事件,当然也可以是其他事件)并 $emit 给父组件来修改父组件的 inputVal 值。当然这是 v-model 默认的情况,我们还可以通过 model 的配置来修改默认的 prop 以及事件。
<!-- 子组件 -->
<template>
<input :value="haha" @input="$emit('setValue', $event.target.value)"/>
</template>
<script>
export default {
model: {
prop: 'haha',
event: 'setValue'
}
props: ['haha']
}
</script>
上面的示例中我们修改了 model ,将子组件从父组件收到的 prop 名称变成了 "haha" ,将事件从默认的 input 事件变成了 setValue 事件,同样也实现 v-model 的自定义。
接下来我们实现一个自定义 v-model 的组件
<!-- 子组件 -->
<template>
<div>
<button @click="handleMinus">-</button>
<input ref="input" type="text" :value="haha" @input="handleInput">
<button @click="handlePlus">+</button>
</div>
</template>
<script>
export default {
model: {
prop: 'haha',
event: 'setValue'
},
props: ['haha'],
methods: {
handleInput(e) {
this.$emit('setValue', e.target.value)
},
handleMinus() {
const val = Number(this.$refs.input.value);
this.$emit('setValue', val - 1)
},
handlePlus() {
const val = Number(this.$refs.input.value);
this.$emit('setValue', val + 1)
},
}
}
</script>
因此可以看出v-modal是一个的语法糖
v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 标签使用
value
属性和input
事件; - checkbox 和 radio 标签使用
checked
属性和change
事件; - select 标签使用
value属性和
change
作为事件。