Vue Front-end Инженер

Vue Front-end Инженер

Роадмап навыков для прокачки

Двусторонняя привязка v-model для форм

VueJSFormsРабота с формами

Основная идея

v-model — это директива Vue для двусторонней привязки данных к элементам форм. Она автоматически синхронизирует значение переменной с вводом пользователя. Это синтаксический сахар над :value и @input.

Ключевые аспекты

  • Двусторонняя привязка — изменение переменной обновляет инпут и наоборот
  • Работает с разными типами — text, checkbox, radio, select, textarea
  • Автоматический выбор события — input для текста, change для checkbox/radio
  • Модификаторы — .lazy, .number, .trim для настройки поведения
  • Синтаксический сахар — v-model эквивалентен :value + @input

Поддерживаемые элементы

  • input type="text", type="email", type="password" и другие текстовые
  • input type="checkbox" — привязка к boolean или массиву
  • input type="radio" — привязка к одному значению
  • select — одиночный или множественный выбор
  • textarea — многострочный текст

Частые ошибки

  • Забывают про .value при работе с ref внутри script
  • Используют v-model с нереактивными переменными
  • Путают поведение checkbox с одним значением и массивом
  • Не используют модификатор .number для числовых полей

Рекомендации

  • Используйте ref или reactive для переменных с v-model
  • Применяйте .number для полей с числами
  • Используйте .trim для полей с текстом
  • Для форм с множеством полей удобнее reactive

Введение и проблематика

Работа с формами — одна из базовых задач во фронтенде. Нужно читать значения полей, обновлять их при изменении пользователем, и синхронизировать с состоянием приложения. Директива v-model делает это автоматически.

v-model — синтаксический сахар, который объединяет привязку значения (:value) и обработку события ввода (@input) в одну конструкцию.


Базовая теория

Что такое v-model

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

vue
<script setup>
import { ref } from 'vue'
 
const message = ref('')
</script>
 
<template>
  <input v-model="message" />
  <p>Введено: {{ message }}</p>
</template>

Как работает под капотом

v-model — это сокращение для:

vue
<!-- v-model -->
<input v-model="message" />
 
<!-- Эквивалентно -->
<input
  :value="message"
  @input="message = $event.target.value"
/>

Практические примеры

Текстовые поля

vue
<script setup>
import { ref } from 'vue'
 
const name = ref('')
const email = ref('')
const bio = ref('')
</script>
 
<template>
  <!-- input type="text" -->
  <input v-model="name" placeholder="Имя" />
 
  <!-- input type="email" -->
  <input v-model="email" type="email" placeholder="Email" />
 
  <!-- textarea -->
  <textarea v-model="bio" placeholder="О себе"></textarea>
</template>

Чекбоксы

Одиночный чекбокс привязывается к boolean:

vue
<script setup>
import { ref } from 'vue'
 
const isAgree = ref(false)
</script>
 
<template>
  <label>
    <input v-model="isAgree" type="checkbox" />
    Согласен с условиями
  </label>
  <p>Согласие: {{ isAgree ? 'Да' : 'Нет' }}</p>
</template>

Несколько чекбоксов привязываются к массиву:

vue
<script setup>
import { ref } from 'vue'
 
const selectedFruits = ref([])
</script>
 
<template>
  <label>
    <input v-model="selectedFruits" type="checkbox" value="apple" />
    Яблоко
  </label>
  <label>
    <input v-model="selectedFruits" type="checkbox" value="banana" />
    Банан
  </label>
  <label>
    <input v-model="selectedFruits" type="checkbox" value="orange" />
    Апельсин
  </label>
  <p>Выбрано: {{ selectedFruits.join(', ') }}</p>
</template>

Радио-кнопки

vue
<script setup>
import { ref } from 'vue'
 
const gender = ref('')
</script>
 
<template>
  <label>
    <input v-model="gender" type="radio" value="male" />
    Мужской
  </label>
  <label>
    <input v-model="gender" type="radio" value="female" />
    Женский
  </label>
  <p>Выбран: {{ gender }}</p>
</template>

Выпадающий список

vue
<script setup>
import { ref } from 'vue'
 
const selected = ref('')
</script>
 
<template>
  <select v-model="selected">
    <option disabled value="">Выберите город</option>
    <option value="moscow">Москва</option>
    <option value="spb">Санкт-Петербург</option>
    <option value="kazan">Казань</option>
  </select>
  <p>Выбран: {{ selected }}</p>
</template>

Множественный выбор:

vue
<script setup>
import { ref } from 'vue'
 
const selectedCities = ref([])
</script>
 
<template>
  <select v-model="selectedCities" multiple>
    <option value="moscow">Москва</option>
    <option value="spb">Санкт-Петербург</option>
    <option value="kazan">Казань</option>
  </select>
  <p>Выбрано: {{ selectedCities.join(', ') }}</p>
</template>

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

.lazy — обновление по событию change

По умолчанию v-model обновляется на каждый ввод символа. С .lazy — только при потере фокуса:

vue
<input v-model.lazy="message" />

.number — преобразование в число

vue
<script setup>
import { ref } from 'vue'
 
const age = ref(0)
</script>
 
<template>
  <!-- Без .number age будет строкой -->
  <input v-model.number="age" type="number" />
  <p>Возраст: {{ age }} (тип: {{ typeof age }})</p>
</template>

.trim — удаление пробелов

vue
<input v-model.trim="username" />

Комбинирование модификаторов

vue
<input v-model.lazy.trim="email" />

Форма с несколькими полями

vue
<script setup>
import { ref } from 'vue'
 
const name = ref('')
const email = ref('')
const password = ref('')
 
function submit() {
  console.log({
    name: name.value,
    email: email.value,
    password: password.value
  })
}
</script>
 
<template>
  <form @submit.prevent="submit">
    <input v-model="name" placeholder="Имя" />
    <input v-model="email" type="email" placeholder="Email" />
    <input v-model="password" type="password" placeholder="Пароль" />
    <button type="submit">Отправить</button>
  </form>
</template>

Для форм с множеством полей reactive удобнее — не нужно писать .value, и все поля в одном объекте.


Пограничные кейсы

Динамические значения для checkbox/radio

vue
<script setup>
import { ref } from 'vue'
 
const toggle = ref('no')
</script>
 
<template>
  <input
    v-model="toggle"
    type="checkbox"
    true-value="yes"
    false-value="no"
  />
  <p>Значение: {{ toggle }}</p>
</template>

Начальное значение select

⚠️

Если начальное значение v-model не совпадает ни с одним option, select покажет пустое состояние. Добавьте disabled option.

vue
<select v-model="selected">
  <option disabled value="">Выберите...</option>
  <option value="a">A</option>
  <option value="b">B</option>
</select>

Плюсы и минусы v-model

ПлюсыМинусы
Простой синтаксисСкрывает механику работы
Меньше кодаОграниченная кастомизация
Работает с разными типами инпутовМожет быть непонятно новичкам

Вопросы интервьюера

Q: Что такое v-model?

Директива для двусторонней привязки данных к элементам форм. Синхронизирует значение переменной с вводом пользователя.

Q: Чем v-model отличается от :value + @input?

Ничем по функциональности — v-model это сокращение для этой комбинации. Но v-model короче и удобнее.

Q: Какие модификаторы есть у v-model?

.lazy (обновление по change), .number (преобразование в число), .trim (удаление пробелов).

Q: Как работает v-model с checkbox?

С одним checkbox — привязка к boolean. С несколькими checkbox с одной переменной — привязка к массиву выбранных значений.


Источники