логотип PurpleSchool
логотип PurpleSchool

Создание и управление формами в Vue

Автор

Олег Марков

Введение

Создание и управление формами — одна из ключевых задач во фронтенд-разработке. Во Vue работа с формами строится на мощных механизмах привязки данных, реактивности и удобных директивах. Даже если у вас нет опыта с Vue, вы быстро поймете, как связать ваши поля ввода с переменными приложения, обрабатывать события ввода, валидировать данные и реагировать на пользовательские действия.

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


Базовые принципы работы с формами в Vue

Двусторонняя привязка с помощью v-model

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

Давайте разберем на простом примере:

<template>
  <div>
    <input v-model="userName" placeholder="Введите ваше имя" />
    <p>Ваше имя: {{ userName }}</p>
  </div>
</template>

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

// Здесь изменяя содержимое поля input, вы сразу же увидите изменения в переменной userName и наоборот.

Vue поддерживает v-model для большинства стандартных элементов формы:

  • <input> (type="text", "password", "email" и т.д.)
  • <textarea>
  • <select>

Привязка к различным типам input

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

<input v-model="textValue" type="text" />

Чекбоксы

<input type="checkbox" v-model="checked" />

// Если вам нужно массив значений:

<input type="checkbox" v-model="checkedItems" value="option1">
<input type="checkbox" v-model="checkedItems" value="option2">

Радиокнопки

<input type="radio" v-model="picked" value="A" />
<input type="radio" v-model="picked" value="B" />

Селекты

<select v-model="selected">
  <option disabled value="">Пожалуйста, выберите</option>
  <option value="one">Один</option>
  <option value="two">Два</option>
</select>

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

<select v-model="selectedOptions" multiple>
  <option value="a">A</option>
  <option value="b">B</option>
</select>

// Обратите внимание, что при multiple получаете массив в selectedOptions.

Синтаксис v-model: сокращения и modifiers

У v-model есть модификаторы, которые помогают управлять обработкой ввода:

  • .lazy — обновляет значение не сразу при вводе, а когда событие change.
  • .number — автоматически преобразует введенное значение в число.
  • .trim — убирает пробелы по краям строки.

Пример:

<input v-model.lazy="age" type="number" />
<input v-model.number="age" type="number" />
<input v-model.trim="name" />

// Используйте эти модификаторы, когда важно контролировать тип данных и момент их обновления.


Управление состоянием и структурами данных формы

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

Если у вас сложная форма, удобно описывать ее как объект:

data() {
  return {
    form: {
      name: '',
      email: '',
      agreeRules: false
    }
  }
}

И тогда, например, поля формы можно связать так:

<input v-model="form.name" placeholder="Имя" />
<input v-model="form.email" placeholder="Email" />
<input type="checkbox" v-model="form.agreeRules" /> Я принимаю правила

Динамические формы

Иногда количество полей заранее неизвестно. Например, список контактов, который пользователь может дополнять.

<template>
  <div>
    <div v-for="(contact, index) in contacts" :key="index">
      <input v-model="contact.value" placeholder="Контакт" />
      <button @click="removeContact(index)">Удалить</button>
    </div>
    <button @click="addContact">Добавить контакт</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      contacts: [ { value: '' } ]
    }
  },
  methods: {
    addContact() {
      this.contacts.push({ value: '' })
    },
    removeContact(index) {
      this.contacts.splice(index, 1)
    }
  }
}
</script>

// Здесь вы можете динамически добавлять и удалять поля формы.


Обработка событий формы

Получение данных при отправке формы

Используйте событие submit на форме, чтобы обрабатывать отправку:

<template>
  <form @submit.prevent="submitForm">
    <input v-model="formData.name" required />
    <input v-model="formData.email" required />
    <button type="submit">Отправить</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        name: '',
        email: ''
      }
    }
  },
  methods: {
    submitForm() {
      // Здесь вы получаете доступ к formData с введенными значениями
      console.log('Форма отправлена', this.formData)
      // Можно отправить данные на сервер или сделать другую обработку
    }
  }
}
</script>

// .prevent предотвращает стандартное поведение браузера (перезагрузку страницы).

Валидация обязательных полей

Чтобы проверить корректность данных ввода, можно добавить простую проверку прямо в метод отправки:

methods: {
  submitForm() {
    if (!this.formData.name || !this.formData.email) {
      alert('Заполните все поля!');
      return;
    }
    // Дальнейшая обработка
  }
}

// Этот подход подойдет для простейшей валидации.


Валидация данных: подходы и инструменты

Ручная валидация

Для простых проверок пишите проверки внутри методов, используемых для обработки формы.

methods: {
  submitForm() {
    if (!this.formData.email.includes('@')) {
      this.errors.email = 'Некорректный email';
      return;
    }
  }
}

Динамическое отображение ошибок

Добавьте переменную errors в состояние формы, чтобы показывать пользователю сообщения об ошибках:

data() {
  return {
    formData: { name: '', email: '' },
    errors: {}
  }
},
methods: {
  submitForm() {
    this.errors = {};
    if (!this.formData.name) this.errors.name = "Имя обязательно";
    if (!this.formData.email) this.errors.email = "Email обязателен";
    else if (!this.formData.email.includes('@')) this.errors.email = "Email некорректен";
    if (Object.keys(this.errors).length > 0) return;
    // Отправить форму
  }
}

А для вывода в шаблоне:

<input v-model="formData.name" />
<span v-if="errors.name">{{ errors.name }}</span>

Использование готовых решений (vee-validate, vuelidate и др.)

Для более сложной логики и минимизации "ручной работы" рекомендуют использовать сторонние библиотеки валидации.

vee-validate

Vee-validate — самая популярная библиотека валидации для Vue. Она отлично интегрируется с v-model и поддерживает шаблонную и программную работу с ошибками.

Установка (npm):

npm install vee-validate yup

Пример использования (Vue 3):

<script setup>
import { useForm, useField } from 'vee-validate'
import * as yup from 'yup'

const { handleSubmit, errors } = useForm({
  validationSchema: yup.object({
    email: yup.string().email().required(),
    password: yup.string().min(6).required()
  })
})

const { value: email } = useField('email')
const { value: password } = useField('password')

const onSubmit = handleSubmit(values => {
  // Значения, прошедшие валидацию, доступны в values
  console.log(values)
})
</script>

<template>
  <form @submit="onSubmit">
    <input v-model="email" placeholder="Email" />
    <span>{{ errors.email }}</span>
    <input v-model="password" type="password" placeholder="Пароль" />
    <span>{{ errors.password }}</span>
    <button type="submit">Войти</button>
  </form>
</template>

vuelidate

Vuelidate — гибкая альтернатива для декларативного описания правил:

npm install @vuelidate/core @vuelidate/validators

В примерах документации показано, как легко создавать сложную логику без шаблонных проверок.


Продвинутые возможности форм в Vue

Кастомные компоненты формы с поддержкой v-model

Вы можете реализовать свои компоненты полей, которые будут так же удобно интегрироваться с v-model.

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

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

// Теперь этим компонентом можно пользоваться с v-model:

<custom-input v-model="formData.name" />

Управление фокусом и доступностью

Vue легко комбинируется с нативными возможностями DOM. Например, можно программно фокусировать элемент:

<template>
  <input ref="emailInput" v-model="email" />
  <button @click="focusEmail">Фокус на email</button>
</template>

<script>
export default {
  data() { return { email: '' }},
  methods: {
    focusEmail() {
      this.$refs.emailInput.focus()
    }
  }
}
</script>

// Вы можете улучшать доступность формы: использовать вопросы, aria-метки, роли.

Моментальная и отложенная валидация

Часто важно показывать ошибки либо сразу при вводе, либо только по попытке отправки.

Это можно гибко настраивать:

// Внести флаг, был ли уже клик "submit"
data() {
  return {
    triedSubmit: false,
    formData: { ... },
    errors: {}
  }
}
...
methods: {
  onInput() {
    if (this.triedSubmit) this.validateFields();
  },
  submitForm() {
    this.triedSubmit = true;
    this.validateFields();
    if (Object.keys(this.errors).length > 0) return; // Не отправлять если есть ошибки
    // отправить
  },
  validateFields() {
    // валидация как раньше
  }
}

// Это позволит управлять моментом показа ошибок.

Асинхронная валидация

Если нужно валидировать поле по данным с сервера (например, имя пользователя уже занято):

methods: {
  async validateUsername() {
    let response = await fetch(`/api/check-username?name=${this.formData.username}`);
    let data = await response.json();
    this.errors.username = data.exists ? "Имя занято" : "";
  }
}

// Обычно асинхронные проверки делают при блюре поля (аналог change/input).


Работа с формами во Vue 3 Composition API

Vue 3 предлагает новый синтаксис работы с состоянием — Composition API. Управление формой реализуется во многом схоже, но с использованием ref и reactive:

<script setup>
import { ref, reactive } from 'vue';

const name = ref('')
const form = reactive({
  email: '',
  agree: false
})

function submit() {
  // Используйте form.email, name.value и др.
}
</script>

<template>
  <form @submit.prevent="submit">
    <input v-model="name" />
    <input v-model="form.email" />
    <input type="checkbox" v-model="form.agree" />
    <button type="submit">OK</button>
  </form>
</template>

// Работа с формами в Composition API может быть гибкой и лаконичной.


Заключение

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


Частозадаваемые технические вопросы

Как сбросить поля формы в начальное состояние?

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

resetForm() {
  this.form = { name: '', email: '', agreeRules: false }
}

Как валидировать числовые поля или даты?

Используйте модификатор .number на v-model для чисел и отдельные библиотеки (например, date-fns, dayjs) либо встроенные проверки для даты:

<input v-model.number="form.age" type="number" />
// Проверяйте: Number.isFinite(form.age)

Как получить доступ к значениям формы через ref?

В Vue 3 используйте ref к форме:

<template>
  <form ref="myFormRef" ...>
</template>
<script setup>
import { ref } from 'vue';
const myFormRef = ref(null)
// myFormRef.value.elements обращение к элементам формы
</script>

Как валидировать каждое изменение (реализация onBlur/onInput)?

Используйте события input или blur для вызова метода проверки:

<input v-model="field" @blur="validateOnBlur" @input="validateOnInput" />

Как сделать автосохранение значений формы?

Следите за объектом формы с помощью watch, и при каждом изменении отправляйте значения:

watch: {
  form: {
    handler(newVal) {
      // отправить newVal на сервер или в localStorage
    },
    deep: true
  }
}
Стрелочка влевоОрганизация сеток и гридов для верстки интерфейсов на VueОрганизация файлов и структура проекта Vue.jsСтрелочка вправо

Все гайды по Vue

Руководство по валидации форм во Vue.jsРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderИнтеграция Tiptap для создания редакторов на VueУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах VueРабота со SCSS в проектах на Vue для стилизации3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Отправить комментарий