自定义组件的v-model
组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。
按照Vue官网介绍,Vue的双向绑定是一种语法糖。本质上是
“负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。”
<input v-model="parentData">
等价于:
<input
:value="parentData"
@input="parentData = $event.target.value"
>
为什么说上述的原始写法只针对于input 的text呢?
vue官网解释如下:
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
…
以下实例自定义组件 runoob-input, 父组件的 num 的初始值为100,更改子组件的值能实时更新父组件的 num:
<div id="app">
<runoob-input v-model="num"></runoob-input>
<p>输入的数字为:{{num}}</p>
</div>
<script>
Vue.component('runoob-input', {
template: `
<p> <!--包含了名为 input 的事件-->
<input
ref="input"
:value="value"
@input="$emit('input', $event.target.value)"
>
</p>
`,
props:['value'],
})
new Vue({
el: "app",
data: {
num: 100,
}
})
</script>
由于 v-model 默认传入的是 value,不是 checked,所以对于复选框或者单选框的组件时,我们需要使用 model 选项,model 选项可以指定当前的事件类型和传入的 props。(也就是给组件添加自定义事件的双向绑定)
<div id="app">
<base-checkbox v-model="lovingVue"></base-checkbox>
<div v-show="lovingVue">
如果选择框打勾我就会显示。
</div>
</div>
<script>
// 注册
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change' // onchange 事件
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
// 创建根实例
new Vue({
el: '#app',
data: {
lovingVue: true
}
})
</script>
实例中 lovingVue 的值会传给 checked 的 prop,同时当 触发 change 事件时, lovingVue 的值也会更新。
具体解析如下:
为了实现给组件添加自定义事件的双向绑定,我们需要为我们的组件增加一个model对象,并在model对象中告知vue框架本次双向绑定对应的属性和事件。
如下示例则是告知vue底层该组件监听checked属性的change事件。
model: {
prop: 'checked',
event: 'change'
},
给组件添加自定义事件的双向绑定的具体步骤如下:
- 第一步为组件增加model对象
model: {
prop: 'checked',
event: 'change'
},
- 第二步在组件的props中注册checked属性
props:{
checked: Boolean
}
- 第三步修改template,增加checkbox和选中的状态描述。需要注意的是:需要使用完全实现v-model的本质上的属性绑定和事件编码。
<input
type="checkbox"
:checked="checked"
@change="$emit('change', $event.target.checked)"
>
4.最后我们在APP.vue中的template中使用 base-checkbox 时就可以通过v-model来实现 base-checkbox 组件的双向绑定了。
<base-checkbox v-model="lovingVue"></base-checkbox>