Двусторонняя привязка данных: v-model

Двусторонняя привязка данных в Vue.js позволяет синхронизировать состояние пользовательского интерфейса с данными компонента. Ключевой механизм для реализации такой связи — директива v-model. Она обеспечивает автоматическое обновление данных при изменении значений в форме и, наоборот, обновление отображения при изменении данных в компоненте.

Основы работы v-model

v-model связывает значение элемента формы с переменной из состояния компонента:

<input v-model="username" type="text">
<p>Привет, {{ username }}!</p>
export default {
  data() {
    return {
      username: ''
    }
  }
}

В этом примере любое изменение текста в поле ввода автоматически изменяет значение username, а изменение username в коде компонента моментально отражается в поле ввода.

Привязка к разным типам элементов

v-model поддерживает различные типы элементов формы:

  • Текстовые поля и textarea: связывают значение с переменной строки.

  • Чекбоксы: связывают с булевым значением или массивом.

    <input type="checkbox" v-model="isSubscribed">
  • Радиокнопки: связывают с одной переменной, значение которой соответствует выбранной кнопке.

    <input type="radio" value="male" v-model="gender"> Мужчина
    <input type="radio" value="female" v-model="gender"> Женщина
  • Селекты (select): связывают с переменной, значение которой соответствует выбранной опции. Для множественного выбора используется массив.

    <select v-model="selectedFruits" multiple>
      <option value="apple">Яблоко</option>
      <option value="banana">Банан</option>
    </select>

Использование v-model в компонентах

v-model может применяться не только к стандартным элементам, но и к пользовательским компонентам. Для этого компонент должен поддерживать передачу значения через value (или modelValue в Vue 3) и эмит события input (или update:modelValue):

// Компонент CustomInput.vue
export default {
  props: {
    modelValue: String
  },
  emits: ['update:modelValue'],
  template: `<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">`
}

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

<CustomInput v-model="username"/>

При изменении значения в CustomInput переменная username автоматически обновляется.

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

v-model поддерживает модификаторы для управления поведением привязки:

  • .lazy – обновление данных происходит не при каждом вводе, а при событии change.

    <input v-model.lazy="username">
  • .number – автоматически преобразует ввод к числу.

    <input v-model.number="age" type="text">
  • .trim – удаляет пробелы с начала и конца строки.

    <input v-model.trim="name">

Эти модификаторы позволяют сократить количество дополнительной обработки данных в коде.

Динамическое связывание и несколько v-model

Vue 3 позволяет использовать несколько v-model на одном компоненте с указанием имени привязки:

<MyComponent v-model:title="pageTitle" v-model:content="pageContent"/>

В компоненте необходимо определить соответствующие props и события update:title и update:content. Это расширяет возможности компонентов, делая их более гибкими для управления сложными формами и состоянием.

Внутренняя реализация

При использовании v-model Vue создаёт синхронизацию между состоянием данных и DOM через реактивную систему. При изменении переменной срабатывает реактивный механизм, который обновляет DOM. При изменении значения в элементе формы срабатывает событие input или change, которое обновляет переменную в состоянии.

Практические советы

  • Для сложных форм часто используют объект состояния для хранения всех полей, что упрощает передачу данных и обработку событий.

    data() {
      return {
        form: {
          username: '',
          email: '',
          agree: false
        }
      }
    }
  • При связывании компонентов через v-model важно придерживаться соглашений о props и событиях, чтобы сохранить двустороннюю привязку.

  • Модификаторы позволяют уменьшить дублирование кода и управлять форматированием данных прямо на уровне шаблона.

Двусторонняя привязка данных с помощью v-model является фундаментальным инструментом Vue.js, который упрощает работу с формами, компонентами и динамическим состоянием интерфейса. Она позволяет создавать реактивные и интерактивные приложения с минимальными затратами кода.