返回

Vue 自定义组件实现 v-model 的几种方式

开发工具

在 Vue 中,v-model 是一个常用的指令,用于实现表单元素和组件之间的双向绑定。当我们使用原生的表单元素时,直接使用 v-model 是很方便的,但是对于自定义组件来说,要实现类似的双向绑定就需要我们自己动手了。

本文介绍了三种实现 Vue 自定义组件 v-model 的方法,分别为:

  • 使用 props 和 events
  • 使用 provide 和 inject
  • 使用自定义指令

1. 使用 props 和 events

这种方法是最简单和最常用的方法。

首先,我们需要在自定义组件中定义一个 prop 来接收父组件传过来的值。

export default {
  props: {
    value: {
      type: String,
      default: ''
    }
  }
}

然后,我们需要在自定义组件中定义一个 event 来通知父组件值的变化。

export default {
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  methods: {
    emitInput(value) {
      this.$emit('input', value)
    }
  }
}

最后,在父组件中,我们需要使用 v-model 来绑定自定义组件的 value prop 和 input event。

<template>
  <custom-component v-model="value"></custom-component>
</template>

<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>

2. 使用 provide 和 inject

这种方法可以让我们在自定义组件中访问父组件的 data 和 methods。

首先,我们需要在父组件中定义一个 provide 对象。

export default {
  provide() {
    return {
      value: this.value
    }
  },
  data() {
    return {
      value: ''
    }
  }
}

然后,我们需要在自定义组件中使用 inject 来注入父组件的 provide 对象。

export default {
  inject: ['value'],
  methods: {
    emitInput(value) {
      this.$emit('input', value)
    }
  }
}

最后,在父组件中,我们需要使用 v-model 来绑定自定义组件的 input event。

<template>
  <custom-component v-on:input="value = $event"></custom-component>
</template>

<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>

3. 使用自定义指令

这种方法可以让我们在自定义组件中使用 v-model 指令。

首先,我们需要定义一个自定义指令。

Vue.directive('model', {
  bind(el, binding) {
    el.addEventListener('input', (e) => {
      binding.value(e.target.value)
    })
  },
  update(el, binding) {
    el.value = binding.value
  }
})

然后,我们需要在自定义组件中使用自定义指令。

<template>
  <input v-model="value"></input>
</template>

<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>

最后,在父组件中,我们需要使用 v-model 来绑定自定义组件的 value prop。

<template>
  <custom-component v-model="value"></custom-component>
</template>

<script>
export default {
  data() {
    return {
      value: ''
    }
  }
}
</script>