Глобальные хуки beforeResolve

Глобальные хуки маршрутизатора — это функции, которые позволяют перехватывать навигацию между маршрутами на уровне всего приложения. Среди них особое место занимает хук beforeResolve, который выполняется после всех beforeEach и beforeEnter хуков, но до того, как компонент маршрута будет подтвержден и отрендерен. Это делает его идеальным для окончательной проверки или подготовки данных перед отображением нового маршрута.

Порядок выполнения глобальных хуков

При навигации между маршрутами Vue Router выполняет хуки в следующем порядке:

  1. beforeEach (глобальные до проверки конкретного маршрута)
  2. beforeEnter (локальные на уровне конкретного маршрута)
  3. beforeResolve (глобальные после всех предыдущих хуков)
  4. beforeRouteEnter (локальные на уровне компонента)
  5. Завершение навигации и рендеринг компонента

Таким образом, beforeResolve является последней возможностью вмешаться перед завершением навигации.

Подключение глобального beforeResolve

Для регистрации хука используется метод router.beforeResolve, который принимает одну функцию с параметрами (to, from, next):

import { createRouter, createWebHistory } from 'vue-router';
import Home from './components/Home.vue';
import Profile from './components/Profile.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/profile', component: Profile }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

// Глобальный beforeResolve
router.beforeResolve((to, from, next) => {
  console.log('Навигация подтверждена, данные можно загружать');
  next();
});

export default router;

Здесь to — объект маршрута, куда осуществляется переход, from — маршрут, с которого выполняется переход, а next — функция продолжения навигации.

Основные сценарии использования

  1. Загрузка данных перед окончательной навигацией Если требуется подгрузить данные, которые должны быть готовы до рендера компонента, beforeResolve позволяет это сделать, не блокируя глобальные или локальные хуки:
router.beforeResolve(async (to, from, next) => {
  try {
    await store.dispatch('fetchUserData', to.params.id);
    next();
  } catch (error) {
    next('/error');
  }
});
  1. Подтверждение действий пользователя Иногда необходимо запросить подтверждение перед сменой маршрута, например, если есть несохранённые изменения:
router.beforeResolve((to, from, next) => {
  if (store.state.unsavedChanges) {
    const confirmed = window.confirm('Есть несохранённые изменения. Продолжить?');
    if (confirmed) next();
    else next(false);
  } else {
    next();
  }
});
  1. Отслеживание навигации для аналитики beforeResolve удобно использовать для регистрации аналитических событий, когда переход уже одобрен:
router.beforeResolve((to) => {
  analytics.trackPageView(to.fullPath);
});

Отличие от beforeEach и beforeEnter

  • beforeEach вызывается до всех локальных хуков маршрутов и может заблокировать навигацию на ранней стадии.
  • beforeEnter применяется на уровне конкретного маршрута и выполняется после beforeEach.
  • beforeResolve гарантированно выполняется после всех beforeEach и beforeEnter, что делает его безопасным для операций, которые должны происходить только при подтверждённой навигации.

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

Функция next в beforeResolve поддерживает три способа использования:

  • next() — продолжить навигацию.
  • next(false) — отменить навигацию.
  • next({ path: '/login' }) — перенаправить на другой маршрут.
router.beforeResolve((to, from, next) => {
  if (!store.state.isAuthenticated && to.meta.requiresAuth) {
    next({ path: '/login' });
  } else {
    next();
  }
});

Асинхронные операции и ожидание

Хук beforeResolve полностью поддерживает асинхронные операции. Это особенно важно для загрузки данных через API, где необходимо дождаться ответа перед отображением компонента. Если next() вызывается после завершения асинхронной функции, навигация будет приостановлена до завершения загрузки.

router.beforeResolve(async (to, from, next) => {
  try {
    const response = await fetch(`/api/data/${to.params.id}`);
    const data = await response.json();
    store.commit('setData', data);
    next();
  } catch {
    next('/error');
  }
});

Практические советы

  • Использовать beforeResolve только для операций, которые требуют подтверждённой навигации.
  • Не перегружать хуки тяжелыми вычислениями, иначе навигация будет задерживаться.
  • Для глобальной авторизации и проверки прав доступа лучше комбинировать beforeEach для ранней фильтрации и beforeResolve для окончательной проверки или подготовки данных.

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