В Navigo хук — это функция, которая выполняется при
срабатывании определённых событий маршрутизатора. Хуки позволяют
внедрять дополнительную логику перед или после перехода на маршрут.
Ключевыми типами хуков являются: before,
after, error, notFound.
done() могут остановить или
разрешить навигацию.Пример базового использования хуков:
const router = new Navigo('/');
router.on('/home', () => {
console.log('Главная страница');
});
router.hooks({
before: (done, params) => {
console.log('Проверка перед маршрутом', params);
done();
},
after: (params) => {
console.log('Переход завершён', params);
},
notFound: () => {
console.log('Страница не найдена');
}
});
Хуки вызываются при каждом переходе на маршрут, поэтому любые тяжёлые вычисления внутри них могут замедлять работу приложения. Следует:
let cachedData = null;
router.hooks({
before: (done) => {
if (!cachedData) {
cachedData = fetchData(); // тяжёлая операция только один раз
}
done();
}
});
Хук before может срабатывать на маршрутах, где его
выполнение не требуется. Для оптимизации можно фильтровать маршруты:
router.hooks({
before: (done, params, route) => {
if (route.name === 'home') {
performHomeCheck();
}
done();
}
});
Поддержка асинхронных операций через done позволяет
выполнять проверки или загрузку данных без блокировки основного потока.
Важно завершать done() в любом случае, чтобы не
заблокировать навигацию.
router.hooks({
before: async (done) => {
try {
await checkUserAuth();
done();
} catch {
redirectToLogin();
}
}
});
Если несколько маршрутов используют одинаковую проверку, имеет смысл вынести её в отдельную функцию. Это снижает дублирование и ускоряет поддержку кода:
function authGuard(done) {
if (!isAuthenticated()) {
redirectToLogin();
} else {
done();
}
}
router.hooks({
before: authGuard
});
router.hooks().hooks:router.on('/dashboard', {
uses: dashboardHandler,
hooks: {
before: authGuard
}
});
Комбинирование глобальных и локальных хуков позволяет экономно распределять вычисления, выполняя общие проверки глобально, а специфические — локально.
Если приложение содержит сложные динамические страницы, стоит избегать постоянного срабатывания хуков на каждом изменении состояния, которое не связано с маршрутом.
let lastRoute = null;
router.hooks({
before: (done, params, route) => {
if (lastRoute === route.url) {
done(); // пропускаем повторное выполнение
} else {
lastRoute = route.url;
loadRouteData(route).then(done);
}
}
});
Для профилирования важно фиксировать время выполнения хуков:
router.hooks({
before: (done, params, route) => {
const start = performance.now();
done();
console.log(`Before-hook ${route.url} выполнен за ${performance.now() - start}ms`);
}
});
Такой подход позволяет выявить узкие места и оптимизировать конкретные операции, вместо того чтобы изменять всю архитектуру маршрутизатора.
Хуки отлично подходят для динамической загрузки компонентов только при переходе на маршрут:
router.on('/profile', async () => {
const module = await import('./profile.js');
module.renderProfile();
});
Использование хуков перед загрузкой гарантирует проверку прав пользователя или состояния приложения, минимизируя ненужные сетевые запросы.
Если несколько хуков выполняют похожие действия, их можно объединять в цепочку, чтобы уменьшить накладные расходы на вызовы функций:
const hooksChain = [
authGuard,
logNavigation,
prefetchData
];
router.hooks({
before: (done, params, route) => {
let i = 0;
const next = () => {
if (i < hooksChain.length) {
hooksChain[i++](next, params, route);
} else {
done();
}
};
next();
}
});
Это позволяет поддерживать читаемую структуру кода и легко добавлять новые шаги без роста сложности.
Оптимизация хуков в Navigo критична для производительности SPA, особенно при множестве маршрутов и сложной логике загрузки данных. Правильное использование фильтрации, асинхронности, кеширования и централизованной логики обеспечивает быстрый отклик интерфейса и поддерживаемость кода.