Как реализовать модель в пользовательских компонентах ввода?vue-28

Основной принцип работы v-model

v-model в Vue — это синтаксический сахар для:

  1. Привязки значения через value/modelValue (props)
  2. Обработки изменений через input/update:modelValue (events)

Стандартная реализация

<input v-model="searchText">

Эквивалентно:

<input
  :value="searchText"
  @input="searchText = $event.target.value"
>

Реализация для кастомного компонента

Вариант 1: Options API

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  >
</template>

<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

Использование:

<custom-input v-model="userInput" />

Вариант 2: Composition API

<template>
  <input
    :value="props.modelValue"
    @input="emit('update:modelValue', $event.target.value)"
  >
</template>

<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>

Расширенные возможности

1. Кастомные модели

Компонент:

<template>
  <input
    :value="firstName"
    @input="$emit('update:firstName', $event.target.value)"
  >
  <input
    :value="lastName"
    @input="$emit('update:lastName', $event.target.value)"
  >
</template>

<script>
export default {
  props: ['firstName', 'lastName'],
  emits: ['update:firstName', 'update:lastName']
}
</script>

Использование:

<user-name-input
  v-model:firstName="first"
  v-model:lastName="last"
/>

2. Модификаторы v-model

Компонент с обработкой модификаторов:

<template>
  <input
    :value="modelValue"
    @input="updateValue($event.target.value)"
  >
</template>

<script>
export default {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  emits: ['update:modelValue'],
  methods: {
    updateValue(value) {
      let processedValue = value
      if (this.modelModifiers.capitalize) {
        processedValue = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', processedValue)
    }
  }
}
</script>

Использование:

<custom-input v-model.capitalize="text" />

3. Компоненты-обертки для сторонних библиотек

Пример с VeeValidate:

<template>
  <Field
    :value="modelValue"
    @input="handleInput"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  methods: {
    handleInput(value) {
      this.$emit('update:modelValue', value)
    }
  }
}
</script>

Особенности для разных типов ввода

Для чекбоксов:

<input
  type="checkbox"
  :checked="modelValue"
  @change="$emit('update:modelValue', $event.target.checked)"
>

Для селектов:

<select
  :value="modelValue"
  @change="$emit('update:modelValue', $event.target.value)"
>
  <option v-for="option in options" :value="option.value">
    {{ option.text }}
  </option>
</select>

Лучшие практики

  1. Всегда объявляйте props и emits явно
  2. Используйте modelValue как стандартное имя prop (Vue 3)
  3. Для сложных преобразований используйте computed-свойства
  4. При работе с FormData учитывайте особенности сериализации

Резюмируем:

Реализация v-model в кастомных компонентах требует правильной настройки props (для получения значения) и emits (для обновления значения). Vue предоставляет гибкие возможности для создания компонентов ввода с поддержкой стандартного синтаксиса v-model, включая модификаторы и множественные модели.