00000569
v-model只是一个语法糖,等于:value+@input,真正的实现靠的还是: v-bind:绑定响应式数据,触发 input 事件并传递数据 (核心和重点)
<input v-model="something">
其实和下面一样的
<input :value="something" @:input="something = $event.target.value">
因此,对于一个带有 v-model 的输入框组件,它应该:接收一个 value prop,触发 input 事件,并传入新值
自定义myInput组件
<template> <div style="padding-top: 100px;"> <button @click="minu" class="btn">-</button> <input type="text" :value="currentValue" @input="handleInput" /> <button @click="plus" class="btn">+</button> </div> </template> <script> export default { props:['value'], data () { return {} }, computed:{ currentValue:function(){ return this.value } }, methods:{ handleInput:function(event){ var value = event.target.value; console.log(988898) this.$emit('input', value); //触发 input 事件,并传入新值 }, minu:function(){ var value = this.currentValue - 1 this.$emit('input', value); }, plus:function(){ var value = this.currentValue + 1 this.$emit('input', value); }, } } </script> <style type="text/css"> .btn{ width: 60px; } </style>
在页面使用
<template> <div class="hello"> <myInput v-model='name'></myInput> {{name}} <myInput v-model='othername'></myInput> {{othername}} </div> </template> <script> import myInput from "@/components/myInput"; export default { name: 'HelloWorld', data () { return { name:10, othername:6, } }, components: { myInput }, methods:{ } } </script> <style scoped> </style>
效果
总结:
自定义的组件内部一般包含原生的表单组件(当然非表单的组件也可以),然后给原生控件绑定事件,捕捉到原生组件的值,利用 $emit方法,触发input方法,组件监听到 input事件然后把值传入
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。