使用自定义事件的表单输入组件

1
2
3
4
5
6
7
<div id="v-model-example">
<p>{{ message }}</p>
<my-input
label="Message"
v-model="message"
></my-input>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Vue.component('my-input', {
template: '\
<div class="form-group">\
<label v-bind:for="randomId">{{ label }}:</label>\
<input v-bind:id="randomId" v-bind:value="value" v-on:input="onInput">\
</div>\
',
props: ['value', 'label'],
data: function () {
return {
randomId: 'input-' + Math.random()
}
},
methods: {
onInput: function (event) {
this.$emit('input', event.target.value)
}
},
})
new Vue({
el: '#v-model-example',
data: {
message: 'hello'
}
})

{{ message }}

其实就是下面的语法糖。

1
2
3
4
5
6
7
<div id="v-model-example">
<p>{{ message }}</p>
<my-input
label="Message"
v-bind:value="message" v-on:input="onInput"
></my-input>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Vue.component('my-input', {
template: '\
<div class="form-group">\
<label v-bind:for="randomId">{{ label }}:</label>\
<input v-bind:id="randomId" v-bind:value="value" v-on:input="onInput">\
</div>\
',
props: ['value', 'label'],
data: function () {
return {
randomId: 'input-' + Math.random()
}
},
methods: {
onInput: function (event) {
console.log(event.target.value);
this.$emit('input', event.target.value)
}
},
})
new Vue({
el: '#v-model-example',
data: {
message: 'hello'
},
methods: {
onInput:function () {
this.message = arguments[0]
}
}
})

为了看清数据的流向,这里将 v-model 全部改为了 v-bind:valuev-on:input

  1. 创建 Vue 实例时,message 等于 ‘hello’,作为 my-input 组件的 props 传入。此时数据方向是自上而下的。
  2. 在 my-input 组件中的 input 文本框输入时,触发 v-on:input 事件,此事件的处理函数 onInput 又会触发父实例的 v-on:input 事件,父实例的 v-on:input 事件触发后,设置 message 为子组件传过来的值。此时数据方向是自下而上的。