Hooks before

В библиотеке Navigo before является мощным инструментом для управления логикой маршрутов перед их обработкой. Этот хук позволяет выполнить проверку или подготовку данных до того, как сработает основной обработчик маршрута. Основное преимущество — возможность централизованно контролировать доступ к маршрутам и изменять поведение навигации.


Синтаксис before

router.on('/example', () => {
  console.log('Маршрут выполнен');
}, {
  before: (done, params, route) => {
    // Логика перед выполнением маршрута
    done();
  }
});

Параметры хука before:

  • done — функция обратного вызова, которую необходимо вызвать для продолжения маршрута. Если она не вызывается, навигация приостанавливается.
  • params — объект с параметрами маршрута (например, значения из :id).
  • route — объект маршрута, содержащий все его свойства (path, name и т.д.).

Асинхронная логика в before

Хук before может работать асинхронно. Например, проверка авторизации пользователя:

router.on('/dashboard', () => {
  console.log('Доступ к панели управления разрешен');
}, {
  before: (done, params, route) => {
    fetch('/api/check-auth')
      .then(response => response.json())
      .then(data => {
        if (data.authenticated) {
          done();
        } else {
          router.navigate('/login');
        }
      });
  }
});

В этом примере навигация к /dashboard выполняется только если пользователь авторизован. В противном случае происходит перенаправление на /login.


Глобальный before для всех маршрутов

Можно определить хук before для всего роутера:

router.hooks({
  before: (done, params, route) => {
    console.log(`Переход к маршруту: ${route.path}`);
    done();
  }
});

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


Возврат false или блокировка маршрута

Если в before не вызвать done, Navigo не выполнит основной обработчик маршрута. Это позволяет блокировать доступ на уровне маршрута:

router.on('/admin', () => {
  console.log('Админка');
}, {
  before: (done) => {
    const userIsAdmin = false;
    if (userIsAdmin) {
      done();
    } else {
      console.warn('Доступ запрещён');
    }
  }
});

Важно понимать, что блокировка маршрута не перенаправляет автоматически — нужно явно вызывать router.navigate() при необходимости.


Использование с динамическими параметрами

Хук before удобно использовать с динамическими сегментами URL:

router.on('/user/:id', (params) => {
  console.log(`Пользователь с ID: ${params.id}`);
}, {
  before: (done, params) => {
    if (parseInt(params.id) > 0) {
      done();
    } else {
      console.warn('Неверный ID пользователя');
      router.navigate('/error');
    }
  }
});

params позволяет получить значение сегментов URL и выполнить проверку до рендера страницы.


Важные рекомендации

  • Всегда вызывать done(), если маршрут должен быть обработан. Если done() не вызван, навигация останавливается.
  • Не злоупотреблять асинхронностью: длительные операции в before могут замедлить навигацию.
  • Использовать для проверки доступа: авторизация, роли пользователей, состояние сессии.
  • Комбинировать с after: before управляет входом на маршрут, after — действиями после выполнения обработчика.

Примеры продвинутого использования

  1. Отмена перехода при несохранённых данных:
router.on('/form', () => {
  console.log('Форма открыта');
}, {
  before: (done) => {
    if (formIsDirty()) {
      if (confirm('Есть несохранённые данные. Продолжить?')) {
        done();
      }
    } else {
      done();
    }
  }
});
  1. Логирование с задержкой перед маршрутом:
router.on('/delayed', () => {
  console.log('Маршрут с задержкой выполнен');
}, {
  before: (done) => {
    setTimeout(() => {
      console.log('Задержка закончена');
      done();
    }, 1000);
  }
});

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


Совместимость с именованными маршрутами

При использовании именованных маршрутов объект route в before содержит ключ name, что позволяет писать универсальные проверки для группы маршрутов:

router.on({
  'home': '/',
  'profile': '/profile'
}, (params, route) => {
  console.log(`Переход на ${route.name}`);
}, {
  before: (done, params, route) => {
    if (route.name === 'profile' && !userLoggedIn()) {
      router.navigate('/login');
    } else {
      done();
    }
  }
});

before в Navigo обеспечивает мощный контроль над навигацией, позволяя реализовывать авторизацию, валидацию параметров и управление состоянием приложения до того, как основной обработчик маршрута будет вызван. Этот хук является ключевым элементом построения защищённых и динамичных SPA на чистом JavaScript.