v-model для двусторонней привязки

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

Основы использования v-model

Простейший пример двусторонней привязки:

<div v-scope="{ message: 'Привет, Petite-Vue!' }">
  <input v-model="message" type="text">
  <p>{{ message }}</p>
</div>
  • v-scope создаёт локальный контекст с переменной message.
  • Атрибут v-model связывает значение <input> с этой переменной.
  • Любое изменение в поле ввода автоматически обновляет переменную message, а изменения message мгновенно отображаются в DOM.

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

Текстовые поля и textarea работают одинаково:

<input v-model="username" type="text">
<textarea v-model="description"></textarea>

Флажки (checkbox):

  • Для одиночных флажков v-model принимает булево значение:
<div v-scope="{ accepted: false }">
  <input type="checkbox" v-model="accepted"> Согласен с условиями
  <p>Согласие: {{ accepted }}</p>
</div>
  • Для групп флажков переменная должна быть массивом:
<div v-scope="{ selectedOptions: [] }">
  <label><input type="checkbox" value="A" v-model="selectedOptions"> A</label>
  <label><input type="checkbox" value="B" v-model="selectedOptions"> B</label>
  <p>Выбрано: {{ selectedOptions.join(', ') }}</p>
</div>

Радиокнопки (radio):

  • v-model связывает группу радиокнопок с одной переменной. Значение переменной соответствует атрибуту value выбранной кнопки.
<div v-scope="{ choice: '1' }">
  <label><input type="radio" value="1" v-model="choice"> Один</label>
  <label><input type="radio" value="2" v-model="choice"> Два</label>
  <p>Выбран: {{ choice }}</p>
</div>

Селекторы (select):

  • Для одиночного выбора:
<div v-scope="{ selected: 'apple' }">
  <select v-model="selected">
    <option value="apple">Яблоко</option>
    <option value="banana">Банан</option>
  </select>
  <p>Выбрано: {{ selected }}</p>
</div>
  • Для множественного выбора переменная должна быть массивом:
<div v-scope="{ selectedFruits: [] }">
  <select v-model="selectedFruits" multiple>
    <option value="apple">Яблоко</option>
    <option value="banana">Банан</option>
    <option value="orange">Апельсин</option>
  </select>
  <p>Выбрано: {{ selectedFruits.join(', ') }}</p>
</div>

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

Petite-Vue поддерживает модификаторы, которые меняют поведение привязки.

  • .number — автоматически преобразует строку из <input> в число:
<div v-scope="{ age: 0 }">
  <input v-model.number="age" type="number">
  <p>Возраст: {{ age }} (тип: {{ typeof age }})</p>
</div>
  • .trim — удаляет пробелы в начале и конце строки при обновлении переменной:
<div v-scope="{ username: '' }">
  <input v-model.trim="username" type="text">
  <p>Имя пользователя: "{{ username }}"</p>
</div>
  • .lazy — обновляет переменную только при событии change, а не при каждом input:
<div v-scope="{ message: '' }">
  <input v-model.lazy="message" type="text">
  <p>Сообщение: {{ message }}</p>
</div>

Связь с вычисляемыми свойствами

v-model работает с реактивными объектами и вычисляемыми свойствами (getter/setter). Это позволяет создавать динамическую обработку данных:

<div v-scope="{
  firstName: 'Иван',
  lastName: 'Иванов',
  fullName: {
    get() { return firstName + ' ' + lastName },
    set(value) {
      [firstName, lastName] = value.split(' ')
    }
  }
}">
  <input v-model="fullName">
  <p>Имя: {{ firstName }}, Фамилия: {{ lastName }}</p>
</div>

Изменение поля fullName автоматически распределяет значения между firstName и lastName, а изменения отдельных частей обновляют связанное поле.

Ограничения и особенности

  • v-model не поддерживает нативные события, отличные от input/change, без использования модификаторов.
  • Для сложных кастомных компонентов необходимо явно реализовать реактивное свойство через modelValue и событие update:modelValue при использовании композиции.
  • Для массивов и объектов рекомендуется использовать реактивные методы push, splice и подобные, чтобы изменения отслеживались корректно.

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

  • Всегда инициализировать переменные в v-scope, чтобы избежать ошибок реактивности.
  • Для числовых данных использовать .number, чтобы избежать преобразований вручную.
  • В случаях с множественным выбором или массивами проверять структуру данных на соответствие типу поля формы.
  • Для сложной логики привязки к вычисляемым свойствам создавать геттеры и сеттеры, чтобы сохранить двустороннюю синхронизацию.

v-model в Petite-Vue обеспечивает максимально простую и лаконичную двустороннюю привязку, сохраняя лёгкость синтаксиса и реактивность, характерную для миниатюрного фреймворка.