Клиентская маршрутизация — механизм управления состоянием интерфейса и навигацией без перезагрузки страницы. В Riot.js маршрутизация тесно связана с компонентной архитектурой и позволяет создавать динамические одностраничные приложения (SPA).
Маршрутизация в Riot.js строится на принципе соответствия URL-пути и компонента, который должен быть отрисован. Основные элементы:
history.pushState и history.replaceState для
управления URL.Riot.js не предоставляет встроенного роутера, поэтому часто
используются сторонние решения вроде riot-route. Однако
базовые принципы можно реализовать самостоятельно через слежение за
изменением window.location.hash или использованием History
API.
Простейшая настройка с использованием riot-route
выглядит так:
import route from 'riot-route';
import Home from './components/home.riot';
import About from './components/about.riot';
route('/', () => {
mount('#app', Home);
});
route('/about', () => {
mount('#app', About);
});
route.start(true);
Ключевые моменты:
route(path, callback) — задаёт обработчик для
конкретного пути.mount(selector, component) — монтирует компонент в
DOM.route.start() — активирует отслеживание изменений
URL.Маршруты можно параметризовать:
route('/user/:id', (id) => {
mount('#app', User, { userId: id });
});
Здесь :id является динамической частью пути,
передаваемой в компонент через пропсы.
Riot.js поддерживает передачу данных через:
Динамические сегменты URL (:param)
Используются для идентификации ресурсов, например,
/posts/:postId.
Query-параметры Получение через
new URLSearchParams(window.location.search):
route('/search', () => {
const params = new URLSearchParams(window.location.search);
const query = params.get('q');
mount('#app', Search, { query });
});
История браузера играет ключевую роль:
route('/') — установка нового состояния без
перезагрузки.route('/path', true) — позволяет сразу заменить текущий
URL.history.back() и
history.forward() сохраняет корректное поведение кнопок
браузера.Важно учитывать, что при использовании хеша (#)
поведение History API упрощается:
route.base('#');
route('/home', () => mount('#app', Home));
Хеш-маршрутизация не требует настройки серверной части и широко применяется в SPA.
Для оптимизации загрузки крупных приложений компоненты можно подключать динамически:
route('/dashboard', async () => {
const { default: Dashboard } = await import('./components/dashboard.riot');
mount('#app', Dashboard);
});
Такой подход снижает нагрузку на основной бандл и ускоряет первоначальный рендер.
Компоненты, связанные с маршрутами, должны корректно обрабатывать состояние при смене URL. Основные принципы:
store или
глобальном состоянии.// пример хранилища
import { observable } from 'riot-observable';
const store = observable({
user: null
});
store.on('login', (userData) => {
store.user = userData;
});
Компоненты маршрутов могут подписываться на события
store для реактивного обновления данных.
Для плавного UX важно использовать анимации при смене компонентов:
mount('#app', CurrentComponent, {}, () => {
const old = document.querySelector('#app > *:first-child');
old?.classList.add('fade-out');
});
Riot.js позволяет легко интегрировать CSS-анимации и контролировать жизненный цикл компонентов.
route('*', () => {
mount('#app', NotFound);
});
route('/old-path', () => route('/new-path'));
route('/profile', () => {
if (!store.user) {
route('/login');
} else {
mount('#app', Profile);
}
});
Эти принципы позволяют строить мощные SPA на Riot.js с гибкой и безопасной навигацией.