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

Як відстежувати незбережені зміни у Vue-формі й попереджати користувача перед виходом зі сторінки?

Задача: користувач півгодини заповнював форму, випадково клікнув посилання - і все втратив. Потрібні дві речі: знати, чи змінено форму, і перехопити вихід.

1. Чи змінена форма - порівняння з початковим знімком:

import { computed, reactive, ref } from 'vue'

const snapshot = ref(JSON.stringify(initialData))
const form = reactive(structuredClone(initialData))

const isDirty = computed(() => JSON.stringify(form) !== snapshot.value)

function markSaved() {
  snapshot.value = JSON.stringify(form)   // після успішного збереження
}

Порівняння зі знімком краще за прапорець «щось змінювали»: якщо користувач змінив поле й повернув старе значення, форма знову вважається чистою. Для великих форм серіалізація на кожну зміну може бути відчутною - тоді порівнюють лише змінені поля чи беруть meta.dirty з бібліотеки форм.

2. Перехід усередині SPA - guard Vue Router:

import { onBeforeRouteLeave } from 'vue-router'

onBeforeRouteLeave(() => {
  if (isDirty.value && !window.confirm('Є незбережені зміни. Вийти?')) {
    return false   // скасувати навігацію
  }
})

Замість confirm можна показати власне модальне вікно - guard може бути асинхронним і повернути false після відповіді користувача.

3. Закриття вкладки, перезавантаження, зовнішнє посилання - роутер про це не знає, потрібна подія браузера:

function onBeforeUnload(e: BeforeUnloadEvent) {
  if (!isDirty.value) return
  e.preventDefault()
  e.returnValue = ''   // для старіших браузерів
}

onMounted(() => window.addEventListener('beforeunload', onBeforeUnload))
onBeforeUnmount(() => window.removeEventListener('beforeunload', onBeforeUnload))

Браузер покаже власне стандартне повідомлення - свій текст задати неможливо, це захист від зловживань.

Підводні камені:

  • після збереження не оновили знімок - користувач щойно зберіг, а при виході отримує попередження;
  • редирект після збереження спрацьовує раніше за оновлення стану - guard блокує власний перехід застосунку. Оновлюйте знімок до навігації;
  • beforeunload постійно підписаний заважає браузеру використовувати back/forward cache - вішайте обробник лише коли форма змінена;
  • дані з сервера підвантажилися після створення знімка - форма одразу «брудна». Знімок робиться після завантаження;
  • не зловживайте: попередження для пошукового поля чи фільтрів дратує. Лише для форм, де втрата справді болить; для довгих форм краще чернетки в localStorage чи автозбереження.

Докладніше в документації: Vue Router: навігаційні guards у Composition API

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