Для интеграции Universal Router с Svelte необходимо создать единый объект маршрутизатора, который будет управлять состоянием приложения и определять, какой компонент отображать в зависимости от текущего URL.
// router.js
import UniversalRouter from 'universal-router';
import Home from './pages/Home.svelte';
import About from './pages/About.svelte';
import NotFound from './pages/NotFound.svelte';
const routes = [
{ path: '/', action: () => Home },
{ path: '/about', action: () => About },
{ path: '(.*)', action: () => NotFound }
];
const router = new UniversalRouter(routes);
export default router;
Здесь ключевым является массив routes, где каждый объект содержит:
Для Svelte необходимо обновлять отображаемый компонент при изменении URL. Для этого используют реактивную переменную:
// App.svelte
<script>
import { onMount } from 'svelte';
import router from './router.js';
import { writable } from 'svelte/store';
const currentComponent = writable(null);
async function navigate(path) {
const Component = await router.resolve({ pathname: path });
currentComponent.set(Component);
}
onMount(() => {
navigate(window.location.pathname);
window.addEventListener('popstate', () => {
navigate(window.location.pathname);
});
});
</script>
<svelte:component this={$currentComponent} />
Ключевые моменты:
popstate обеспечивает реакцию на кнопки
«назад/вперед» в браузере.router.resolve({ pathname }) возвращает
компонент, который должен быть отображен.Universal Router позволяет создавать маршруты с параметрами, которые
передаются в action:
const routes = [
{
path: '/user/:id',
action: ({ params }) => {
return User; // Можно передавать params в компонент
}
}
];
Чтобы передать параметры в Svelte-компонент:
async function navigate(path) {
const Component = await router.resolve({ pathname: path });
const params = router.resolve({ pathname: path }).params || {};
currentComponent.set({ component: Component, props: params });
}
<svelte:component this={$currentComponent.component} {...$currentComponent.props} />
Так можно использовать динамические сегменты URL внутри компонентов,
например, для загрузки данных пользователя по id.
Для оптимизации можно загружать компоненты по мере необходимости:
const routes = [
{
path: '/',
action: async () => {
const module = await import('./pages/Home.svelte');
return module.default;
}
},
{
path: '/about',
action: async () => {
const module = await import('./pages/About.svelte');
return module.default;
}
}
];
Преимущества:
Для перехода между страницами внутри Svelte-компонента используют
функцию navigate:
<button on:click={() => navigate('/about')}>О нас</button>
Это обновляет URL и текущий компонент без перезагрузки страницы. Для
полной интеграции можно обернуть функцию navigate в store,
чтобы любой компонент имел доступ к переходам.
Universal Router позволяет определять catch-all маршруты и асинхронно обрабатывать ошибки:
const routes = [
{ path: '/', action: () => Home },
{ path: '/about', action: () => About },
{
path: '(.*)',
action: () => NotFound
}
];
router.resolve({ pathname: '/non-existent' })
.catch(error => {
console.error('Ошибка маршрутизации:', error);
});
Использование (.*) гарантирует, что все неопределенные
маршруты попадут на страницу NotFound, а ошибки при
разрешении маршрута можно перехватывать через .catch.
В Svelte можно создавать вложенные маршруты, возвращая объект с
children в action:
const routes = [
{
path: '/dashboard',
action: () => import('./pages/Dashboard.svelte').then(m => m.default),
children: [
{ path: '/stats', action: () => import('./pages/Stats.svelte').then(m => m.default) },
{ path: '/settings', action: () => import('./pages/Settings.svelte').then(m => m.default) }
]
}
];
Для рендеринга вложенных маршрутов создают отдельный компонент
<RouterOutlet />, который получает текущий дочерний
маршрут и отображает его.
<script>
import { writable } from 'svelte/store';
export let child = null;
</script>
{#if child}
<svelte:component this={child.component} {...child.props} />
{/if}
Оптимальная интеграция Universal Router с Svelte предполагает:
router.js с конфигурацией
маршрутов.navigate для изменения
маршрутов.<RouterOutlet />.Эта схема обеспечивает гибкую, модульную маршрутизацию без сторонних heavy-weight решений и легко расширяется для больших Svelte-приложений.