
正文
[ vue ] 自定义组件的 v-model 理解
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
需求场景描述:

1. 在父组件 myself.vue 里面定义数据 button_val
2. 在父组件 myself.vue.里面定义按钮,它的功能是吧 button_val 的值 -1
----
3. 子组件 test.vue 是一个按钮,它显示的数据是 父组件button_val 的值,功能是把 button_val 的值 +1
接下来看如何一步一步实现这个效果
官方文档解读:
查看官方文档:https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model

1. 注意这里组件的默认规则:
prop: value
event: input
2. v-mode是vue提供的语法糖,它本质是这样的:
[ 效果 ]

[ 父组件 ]
<template>
<div class="q-ma-lg">
<div class="q-mb-lg">
<span>(父组件)监控lovingVue的值:</span>
{{lovingVue}}
</div>
<base-checkbox :value="lovingVue" @input="lovingVue = $event"/>
</div>
</template>
<script>
import test_child from 'components/test_child.vue'
export default {
data(){
return {
lovingVue:''
}
},
components:{
'base-checkbox':test_child
}
}
</script>
[ 子组件 ]
<template>
<div>
<span>(子组件)</span>
<input type="text" @input="$emit('input',$event.target.value)"/>
</div>
</template>
<script>
1. 子组件本质是一个input框,通过监听用户input输入来抛出一个值,这个值就是用户输入的内容。
2. 父组件的行为就可以参照官方文档的那句话了: 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
这里父组件监听input事件来获取子组件抛出的值,并更新 lovingVue 。
3. 就此达到数据的双向绑定
3. 自定义prop和自定义事件:
默认v-model的props是:value
默认v-model的event是:input
这里我们来实现自定义prop和事件:
<!-- 父组件 -->
<template>
<div class="q-ma-lg">
<div class="q-mb-lg">
<span>(父组件)监控lovingVue的值:</span>
{{lovingVue}}
</div> <base-checkbox :customValue="lovingVue" @customEvent="lovingVue = $event"/> </div>
</template>
<script>
import test_child from 'components/test_child.vue'
export default {
data(){
return {lovingVue:''}
},
components:{'base-checkbox':test_child}
}
</script><!-- ------------------------------------------------------------------------------- --><!-- 子组件 -->
<template>
<div>
<span>(子组件)</span>
<input type="text" @input="$emit('customEvent',$event.target.value)"/>
</div>
</template><script>
export default {
model:{
prop:'customValue',
event:'customEvent'
},
props:{
customValue:String
}
}
</script>
需求的实现:<!-- 父组件 -->
<template>
<div class="q-mt-lg">
<div style="width:200px;height:100px;border:1px solid" class="bg-primary">
<span>parent</span>
<q-btn
:label="button_val + ' (-1)'"
@click="button_val = button_val - 1"
color="grey"
class="q-ma-md"
/>
</div> <!-- 子组件 -->
<div style="width:200px;height:100px;border:1px solid" class="bg-info">
<span>child</span>
<test
v-model="button_val"
class="q-ma-md"
/>
</div>
</div>
</template>
<script>
import test from 'components/test.vue'
export default {
data(){
return {button_val:1}
},
components:{test}
}
</script>----------------------------------------------<!-- 子组件 -->
<template>
<div>
<q-btn color="primary" :label="buttonVal+' (+1)'" @click="handleTest"/>
</div>
</template><script>
export default {
model:{
prop:'buttonVal',
event:'haha'
},
props:{
buttonVal:{
type:Number,
default:0
} },
data(){
return {}
},
methods:{
handleTest(){
this.$emit('haha',Number(this.buttonVal)+1)
} }
}
</script>
<!-- 父组件 -->
<template>
<div class="q-mt-lg">
<div style="width:200px;height:100px;border:1px solid" class="bg-primary">
<span>parent</span>
<q-btn
:label="button_val + ' (-1)'"
@click="button_val = button_val - 1"
color="grey"
class="q-ma-md"
/>
</div> <!-- 子组件 -->
<div style="width:200px;height:100px;border:1px solid" class="bg-info">
<span>child</span>
<test
v-model="button_val"
class="q-ma-md"
/>
</div>
</div>
</template>
<script>
import test from 'components/test.vue'
export default {
data(){
return {button_val:1}
},
components:{test}
}
</script>----------------------------------------------<!-- 子组件 -->
<template>
<div>
<q-btn color="primary" :label="buttonVal+' (+1)'" @click="handleTest"/>
</div>
</template><script>
export default {
model:{
prop:'buttonVal',
event:'haha'
},
props:{
buttonVal:{
type:Number,
default:0
} },
data(){
return {}
},
methods:{
handleTest(){
this.$emit('haha',Number(this.buttonVal)+1)
} }
}
</script>






