之前一直很好奇
element-ui
自定义组件是怎么实现双向绑定的,后来抽空学习了一下,今天来复习一下加深一下记忆。
首先在components
目录下新建一个名为MyInput
的组件,代码如下:
// v-model 默认接收一个value的参数和向父组件触发一个input的事件
<template>
<div>
<input type="text" :value="value" @input="onInput" />
</div>
</template>
<script>
export default{
props: ['value'],
methods: {
onInput(e){
this.$emit('input', e.target.value)
}
}
}
</script>
然后在父组件引入使用,使用方式如下:
<template>
<div>
<my-input v-model="message"></my-input >
</div>
</template>
<script>
import MyInput from '@/src/components/MyInput.vue'
export default{
components: {
MyInput
},
data(){
return{
message: ''
}
}
}
</script>
v-model
其实就是一个语法糖,就是父组件监听子组件emit
发出的input
事件,然后把子组件传来的值赋给了message
,等同于以下代码:
<my-input :value="message" @input="message = $event"></my-input>
刚才也说了
v-mode
默认接收的props是value
,触发的是input
事件,当然我们也可以通过model
改一下,这样就更灵活了,双向绑定就不仅仅只是适用于input
组件了,就可以像element-ui
那样自定义自己的radio checkbox
组件并可以双向绑定了:
子组件修改如下:
<template>
<div>
<input type="radio" :name="label" :value="label" @click="onChange" :checked="radio === label">
<span>{{label}}</span>
</div>
</template>
<script>
export default{
props: ['label', 'radio'],
model: {
prop: 'radio', //父组件监听到click事件以后就会把label的值赋给radio了
event: 'click' // 父组件的v-model现在默认监听的就是click事件了
},
methods: {
onChange(){
this.$emit('click', this.label)
this.$emit('change', this.label) // 为了像element那样, 我们再派发一个change,方便我们监听回调事件
}
}
}
</script>
父组件修改代码如下:
<template>
<div>
<my-radio v-model="radio" label="label1" @change="onChange"></my-radio>
<my-radio v-model="radio" label="label2" @change="onChange"></my-radio>
</div>
</template>
<script>
import MyRadio from '@/src/components/MyRadio.vue'
export default{
components: {
MyRadio
},
data(){
return{
radio: 'label1' // 默认选中label1
}
},
methods: {
onChange(){
console.log(val)
}
}
}
</script>
现在就可以灵活自定义自己的双向绑定组件了,如果组件使用频繁的话,可以注册到全局组件,就不用一次次引入了。