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

我们在使用Vue自定义组件的时候,通常是利用props和$emit来实现父子组件数据的传输,那么如何实现经典的v-model双向绑定呢。

v-model实际上是个语法糖,可以理解为<input v-bind:value=“value” v-on:input=“$emit(‘input’, $event.target.value)” /> ,我们需要使用这些特性去实现v-model,Vue2和Vue3实现略有不同。

Vue2实现

在Vue2中定义组件时,props为value的属性会默认接收v-model传过来的值,然后子组件向父组件传值时使用$emit(‘update’)回传。子组件编写因为根据规范子组件不能直接绑定props,所以定义了一个data.testValue,同时watch value实时更新testValue, testValue change也通过 this.$emit('update', event.target.value)同步回传到父组件。

子组件代码:

<template>
    <input type="text" v-model="testValue" @change="testValueChange" />
</template>
<script>
export default {
  name: 'Child',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      testValue: ''
    }
  },
  created() {
    this.testValue = this.value
  },
  watch: {
    value() {
      this.testValue = this.value
    }
  },
  methods: {
    testValueChange(event) {
        this.$emit('update', event.target.value)
    }
  },
}
</script>

父组件代码

<template>
    <child v-mode="val" />
</template>
<script>
import Child from './Child.vue'
export default {
  name: 'Parent',
  components: { Child }
  data() {
    return {
      val: ''
    }
  }
}
</script>

Vue3实现

Vue3实现方式略有不同,但原理是一致的,子组件props使用modelValue,回传父组件为emit(‘update:modelValue’)。

子组件代码:

<template>
  <input v-model="testValue" @change="testValueChange" />
</template>

<script> 
import { ref, watch, onMounted } from 'vue'
export default {
  name: 'Parent',
  props: {
    modelValue: {
      type: String,
      default: ''
    }
  },
  setup(props, { emit }) {
    const testValue = ref('')
    onMounted(() => {
      testValue.value = props.modelValue
    })
    watch(
      () => props.modelValue,
      (newVal) => {
        testValue.value = props.modelValue
      }
    )
    testValueChange = (event) {
        emit('update:modelValue', event.target.value)
    }
    return { testValue, testValueChange }
  }
}
</script>

父组件代码:

<template>
  <child v-model="val" />
</template>

<script> 
import { ref } from 'vue'
import Child from 'Child.vue'
export default {
  name: 'Parent',
  setup() {
    const val = ref('') 
    return { val }
  }
}
</script> 

 

You may also like...

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注