Hyperapp — это минималистичный фреймворк для построения веб-приложений на JavaScript, ориентированный на функциональный стиль программирования. Одним из ключевых аспектов современных SPA (Single Page Application) является навигация между различными представлениями без полной перезагрузки страницы. Hyperapp предоставляет инструменты для реализации маршрутизации через встроенные возможности и сторонние решения.
Маршрутизация в Hyperapp обычно строится вокруг состояния
приложения, где текущий маршрут хранится в глобальном состоянии
(state), а отображение компонентов зависит от этого
состояния. Это позволяет легко управлять переходами и интегрировать их с
логикой приложения.
Для реализации маршрутизации первым шагом является расширение состояния:
const state = {
route: '/',
user: null,
};
Здесь route отвечает за текущий путь. Изменение этого
значения приводит к рендерингу соответствующего компонента.
Важно: маршруты лучше хранить в виде строк, а отображение страниц связывать с функциями-компонентами.
Создание диспетчера маршрутов позволяет сопоставлять пути с компонентами:
const routes = {
'/': HomePage,
'/about': AboutPage,
'/profile': ProfilePage,
};
const view = (state, actions) => {
const Component = routes[state.route] || NotFoundPage;
return Component(state, actions);
};
Такой подход упрощает обработку маршрутов и позволяет динамически подгружать компоненты.
Изменение маршрута реализуется через действия (actions):
const actions = {
setRoute: route => state => ({ route })
};
Переход между страницами осуществляется вызовом:
actions.setRoute('/about');
Для синхронизации с браузерной историей используется API
history.pushState и событие popstate:
window.addEventListener('popstate', event => {
actions.setRoute(window.location.pathname);
});
const navigate = path => {
window.history.pushState(null, '', path);
actions.setRoute(path);
};
Теперь изменение маршрута обновляет URL без полной перезагрузки страницы, а состояние приложения остается непрерывным.
Для обработки динамических сегментов пути (/profile/:id)
можно использовать регулярные выражения или специализированные
утилиты:
const matchRoute = path => {
const profileMatch = path.match(/^\/profile\/(\d+)$/);
if (profileMatch) {
return { component: ProfilePage, params: { id: profileMatch[1] } };
}
return { component: routes[path] || NotFoundPage, params: {} };
};
Рендеринг учитывает параметры маршрута:
const view = (state, actions) => {
const { component: Component, params } = matchRoute(state.route);
return Component(state, actions, params);
};
Это позволяет создавать гибкие интерфейсы с динамическими страницами.
Компоненты для ссылок должны предотвращать стандартное поведение
<a> и использовать navigate:
const Link = ({ to, children }) => (state, actions) => (
<a href={to} oncl ick={e => { e.preventDefault(); navigate(to); }}>
{children}
</a>
);
Такой подход обеспечивает управление маршрутизацией через Hyperapp и сохраняет возможности истории браузера.
Для крупных приложений важно уменьшать размер начального бандла. Hyperapp позволяет реализовать ленивую загрузку через динамический импорт:
const routes = {
'/': () => import('./HomePage.js').then(m => m.default),
'/about': () => import('./AboutPage.js').then(m => m.default),
};
const view = async (state, actions) => {
const ComponentLoader = routes[state.route] || (() => NotFoundPage);
const Component = await ComponentLoader();
return Component(state, actions);
};
Такой подход снижает нагрузку на клиент и ускоряет начальную загрузку.
Необходимо предусмотреть сценарии, когда маршрут не найден. Для этого
создается компонент NotFoundPage:
const NotFoundPage = () => (
<div>
<h1>Страница не найдена</h1>
<Link to="/">На главную</Link>
</div>
);
Также можно реализовать редиректы, изменяя состояние маршрута программно.
routes для всех
маршрутов.Маршрутизация в Hyperapp строится на принципах чистого состояния, функций-действий и компонентов, что делает приложения лёгкими, предсказуемыми и легко расширяемыми. Такой подход обеспечивает полный контроль над навигацией и интеграцию с современными возможностями браузера.