Vue 自定义组件实现v-model双向绑定

2021-12-10 10:48:40 浏览数 (1)

之前一直很好奇element-ui自定义组件是怎么实现双向绑定的,后来抽空学习了一下,今天来复习一下加深一下记忆。

首先在components目录下新建一个名为MyInput的组件,代码如下:

代码语言:javascript复制
// 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>  

然后在父组件引入使用,使用方式如下:

代码语言:javascript复制
<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,等同于以下代码:

代码语言:javascript复制
<my-input :value="message" @input="message = $event"></my-input>

刚才也说了v-mode默认接收的props是value,触发的是input事件,当然我们也可以通过model改一下,这样就更灵活了,双向绑定就不仅仅只是适用于input组件了,就可以像element- ui那样自定义自己的radio checkbox组件并可以双向绑定了:

子组件修改如下:

代码语言:javascript复制
<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>  

父组件修改代码如下:

代码语言:javascript复制
<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>  

现在就可以灵活自定义自己的双向绑定组件了,如果组件使用频繁的话,可以注册到全局组件,就不用一次次引入了。

0 人点赞