Прерывание навигации

Vue Router предоставляет мощный механизм управления маршрутизацией в приложениях на Vue.js, включая возможность прерывания или контроля навигации. Прерывание навигации позволяет предотвратить переход на другой маршрут при определённых условиях, что полезно для проверки прав доступа, подтверждения действий пользователя или выполнения асинхронных операций до изменения маршрута.


Навигационные охранники (Navigation Guards)

Навигационные охранники — это функции, которые вызываются перед изменением маршрута. Они позволяют отменять, перенаправлять или задерживать навигацию.

Основные типы охранников:

  1. Глобальные охранники (beforeEach, beforeResolve, afterEach)
  2. Охранники маршрута (в определении маршрута beforeEnter)
  3. Охранники компонентов (beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave)
Глобальные охранники
const router = new VueRouter({ routes });

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !userIsAuthenticated()) {
    next('/login'); // перенаправление
  } else {
    next(); // разрешение навигации
  }
});
  • to — маршрут, на который планируется переход.

  • from — текущий маршрут.

  • next — функция, вызываемая для контроля навигации:

    • next() — разрешает переход.
    • next(false) — отменяет переход.
    • next('/path') — перенаправляет на другой маршрут.
    • next({ name: 'home' }) — можно использовать объект маршрута для редиректа.
Охранники маршрута
const routes = [
  {
    path: '/admin',
    component: AdminPage,
    beforeEnter: (to, from, next) => {
      if (!userIsAdmin()) {
        next('/not-authorized');
      } else {
        next();
      }
    }
  }
];

Особенности beforeEnter:

  • Выполняется только при входе на маршрут, не при обновлении параметров.
  • Позволяет централизованно проверять доступ к конкретному маршруту.
Охранники компонентов
export default {
  beforeRouteEnter(to, from, next) {
    fetchData().then(data => {
      next(vm => vm.setData(data));
    });
  },
  beforeRouteUpdate(to, from, next) {
    if (to.params.id !== from.params.id) {
      next(); // разрешить навигацию
    }
  },
  beforeRouteLeave(to, from, next) {
    if (hasUnsavedChanges()) {
      const answer = window.confirm('Есть несохранённые изменения. Покинуть страницу?');
      if (answer) next();
      else next(false);
    } else {
      next();
    }
  }
}
  • beforeRouteEnter не имеет доступа к this (компонент ещё не создан), можно получить доступ через next(vm => ...).
  • beforeRouteUpdate вызывается, когда изменяются параметры маршрута, но компонент остаётся.
  • beforeRouteLeave позволяет предотвратить уход с текущего компонента, что идеально для форм с несохранёнными данными.

Асинхронные операции и прерывание навигации

Навигация можно задерживать до завершения асинхронных операций, таких как запросы к серверу. next может быть вызван только после завершения этих операций:

router.beforeEach(async (to, from, next) => {
  try {
    const hasPermission = await checkPermission(to);
    if (hasPermission) next();
    else next('/access-denied');
  } catch (error) {
    next(false); // отмена навигации при ошибке
  }
});
  • Асинхронные функции позволяют использовать await внутри охранников.
  • Важно корректно обрабатывать ошибки, чтобы не заблокировать маршрутизацию.

Метаданные маршрутов для контроля навигации

Маршруты могут содержать поле meta, которое удобно использовать для логики охранников:

const routes = [
  {
    path: '/profile',
    component: ProfilePage,
    meta: { requiresAuth: true }
  }
];

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

Преимущества метаданных:

  • Позволяют хранить правила доступа рядом с маршрутом.
  • Снижают дублирование кода охранников.
  • Упрощают динамическую логику маршрутизации.

Отмена навигации в современных версиях Vue Router

Vue Router 4 (для Vue 3) поддерживает новый метод навигации router.push и router.replace, которые возвращают промис. Это позволяет ловить ошибки и отмену навигации:

router.push('/dashboard')
  .catch(err => {
    if (err.name !== 'NavigationDuplicated') {
      console.error(err);
    }
  });
  • Ошибка NavigationDuplicated возникает, если попытка перейти на текущий маршрут.
  • Использование промисов позволяет контролировать поведение при отмене навигации.

Резюме по прерыванию навигации

  • Прерывание навигации осуществляется с помощью охранников и функции next.
  • Можно отменять навигацию, перенаправлять или задерживать её до завершения асинхронных операций.
  • beforeRouteLeave — ключевой инструмент для предотвращения ухода с компонента.
  • Метаданные маршрутов позволяют создавать гибкие и централизованные правила доступа.
  • Асинхронные операции и промисы дают возможность безопасно контролировать маршрутизацию в динамических сценариях.

Прерывание навигации во Vue Router обеспечивает надежный и гибкий контроль поведения приложения, особенно в случаях проверки авторизации, сохранения данных и управления асинхронными процессами.