Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як зберігати стан форми у Vue: reactive чи ref, v-model і скидання форми?

Найпростіший підхід - один реактивний об'єкт з усіма полями форми і v-model на кожному полі:

<script setup lang="ts">
import { reactive, ref } from 'vue'

const initial = () => ({ name: '', email: '', role: 'editor', agree: false })

const form = reactive(initial())
const submitting = ref(false)

async function submit() {
  submitting.value = true
  try {
    await api.post('/users', { ...form })
    Object.assign(form, initial())   // скидання
  } finally {
    submitting.value = false
  }
}
</script>

<template>
  <form @submit.prevent="submit">
    <input v-model.trim="form.name" />
    <input v-model="form.email" type="email" />
    <select v-model="form.role">
      <option value="editor">Редактор</option>
      <option value="admin">Адміністратор</option>
    </select>
    <input v-model="form.agree" type="checkbox" />
    <button :disabled="submitting">Зберегти</button>
  </form>
</template>

reactive чи ref:

reactive({...}) ref({...})
доступ у <script> form.email form.value.email
замінити весь об'єкт ні - лише Object.assign так: form.value = initial()
деструктуризація ламає реактивність теж ламає (form.value - реактивний об'єкт)

ref зручніший, коли форму треба повністю замінити (завантажили дані для редагування). reactive - коротший запис полів.

Модифікатори v-model: .trim прибирає пробели, .number перетворює на число, .lazy оновлює значення на change, а не на кожен введений символ.

Типові помилки:

  • @submit без .prevent - браузер відправляє форму звичайним запитом і перезавантажує сторінку;
  • скидання через form = initial() для reactive - зміниться лише локальна змінна, а шаблон лишиться прив'язаним до старого об'єкта;
  • відправка самого реактивного проксі - бібліотеки зазвичай серіалізують його коректно, але безпечніше передавати звичайну копію ({ ...form } чи toRaw(form));
  • checkbox для масиву: кілька чекбоксів з одним v-model і масивом у стані дають список вибраних значень;
  • немає захисту від подвійного кліку - кнопка має бути вимкнена на час відправки.

Для складних форм (валідація, вкладені масиви, стан «змінено») варто взяти бібліотеку форм, а не винаходити все самому.

Докладніше в документації: Vue: прив'язка полів форми

Схожі питання