自定义组件的v-model
v-model指令非常好用,直接可以让表单元素的值与data中的值实现双向绑定:
<div id="app">
<input type="text" v-model="msg">
</div>
var app = new Vue({
el: '#app',
data: {
msg: ''
}
})
这样msg的值就与input的输入绑定了。
如果我们自定义了一个表单组件,想用v-model来绑定数据,要怎么做呢?
定义好组件后,直接在组件上使用v-model,是实现不了的
<div id="app">
<my-input v-model="msg"></my-input>
<p>{{msg}}</p>
</div>
Vue.component('my-input', {
template: `<input type="text" >`
})
var app = new Vue({
el: '#app',
data: {
msg: '我是msg'
}
})
无论你在input中怎么输入,p元素中的内容都不会变。
要想在自定义表单组件中使用v-model,先要知道v-model是怎么实现的。
v-model是一个语法糖,不使用语法糖就是这样写(不同的输入控件写法可能不一样,后面会提到):
<div id="app">
<input type="text" :value="msg" @input="msg = $event.target.value">
</div>
var app = new Vue({
el: '#app',
data: {
msg: ''
}
})
:value=“msg”: msg的值是啥,input中显示的就是啥
@input=“msg = $event.target.value”: input中输入啥,msg就变成啥
这样成完成了双向绑定。
知道了它的实际实际写法,在自定义组表单件中,如果不使用语法糖来实现的话,那就是这样:
<div id="app">
<my-input :value="msg" @input="msg = $event"></my-input>
<p>{{msg}}</p>
</div>
Vue.component('my-input', {
props: {
value: String // 需要接收父组件传来的value
},
template: `<input type="text" :value="value" @input="$emit('input', $event.target.value)">`
})
var app = new Vue({
el: '#app',
data: {
msg: '我是msg'
},
})
子组件接收父组件传来的value,并v-bind到自己的value
子组件的input事件来触发父组件的input事件,并将input的value值作为参数传递到父组件。
这样确实是实现了,但是我说好的用v-model呢,是不是只要在my-input组件调用的时候使用v-model就行了呢:
<div id="app">
<my-input v-model="msg"></my-input>
<p>{{msg}}</p>
</div>
Vue.component('my-input', {
props: {
value: String // 需要接收父组件传来的value
},
template: `<input type="text" :value="value" @input="$emit('input', $event.target.value)">`
})
var app = new Vue({
el: '#app',
data: {
msg: '我是msg'
},
})
运行一下,好像就是这个样子,是不是没有问题了呢?
我在官网上看到这样一句话:
“一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突。”
智能翻译器:v-model会默认使用元素的value值和input事件,但有的输入控件关键的值不是value,或者没有input事件,自定义表单组件的v-model就会有问题,需要用model选项来处理这种问题。
以下几种输入控件对比一下:
<!--value为关键值, 用input事件来修改值-->
<input type="text" >
<!--value为关键值, 用change事件来修改值-->
<select>
<option value="1">第一个选项</option>
<option value="2">第二个选项</option>
<option value="3">第三个选项</option>
</select>
<!--checked为关键值, 用change事件来修改值-->
<input type="checkbox" >
刚刚我们写的my-input组件的完整写法是这样
<div id="app">
<my-input v-model="msg"></my-input>
<p>{{msg}}</p>
</div>
Vue.component('my-input', {
model: {
prop: 'value',
event: 'input'
},
props: {
value: String
},
template: `<input type="text" :value="value" @input="$emit('input', $event.target.value)">`
})
var app = new Vue({
el: '#app',
data: {
msg: '我是msg'
},
})
如果我们用的是checkbox,借用一下官网的demo:
Vue.component('base-checkbox', {
model: {
prop: 'checked', // 输入控件的'关键值'
event: 'change' // 用于修改值的事件
},
props: {
checked: Boolean
},
template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" >`
})
就到这里了,谢谢浏览!