Atomico предоставляет современный подход к построению клиентских приложений на базе веб-компонентов. Одним из ключевых аспектов динамических интерфейсов является client-side навигация, позволяющая менять содержимое страницы без полной перезагрузки. В контексте Atomico она реализуется с использованием встроенных хуков и управления состоянием маршрутов.
В Atomico маршрутизация строится вокруг объекта
useRoute, который отслеживает текущий путь и
параметры URL. Он предоставляет два основных инструмента:
route — реактивное значение текущего пути;params — объект с параметрами маршрута, извлечёнными из
URL.Пример базовой настройки маршрута:
import { c, useRoute, html } from "atomico";
function App() {
const { route, params } = useRoute({
routes: [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/user/:id", component: User }
]
});
return html`
<nav>
<a href="/" onCl ick=${navigate}>Главная</a>
<a href="/about" onCl ick=${navigate}>О сайте</a>
</nav>
<main>
${route.component({ params })}
</main>
`;
}
function navigate(event) {
event.preventDefault();
history.pushState({}, "", event.currentTarget.href);
window.dispatchEvent(new Event("popstate"));
}
В этом примере:
routes определяет список маршрутов и соответствующих
компонентов.navigate предотвращает стандартное поведение
ссылок и обновляет URL без перезагрузки страницы.popstate инициирует обновление текущего маршрута.Маршруты с динамическими сегментами позволяют получать параметры напрямую:
function User({ params }) {
return html`<h1>Пользователь ID: ${params.id}</h1>`;
}
При переходе на /user/42 значение params.id
будет равно "42". Atomico автоматически сопоставляет
сегменты пути с именованными параметрами.
Для обновления интерфейса при изменении URL используется реактивное
свойство route.path. Например, можно условно отображать
компонент на основе текущего пути:
const { route } = useRoute({ routes });
watchEffect(() => {
console.log("Текущий путь:", route.path);
});
watchEffect отслеживает любые изменения в
route и запускает реакцию автоматически, что позволяет
создавать сложные динамические интерфейсы без сторонних библиотек.
Atomico поддерживает вложенные маршруты, что особенно полезно для построения многоуровневой навигации:
const { route } = useRoute({
routes: [
{
path: "/dashboard",
component: Dashboard,
children: [
{ path: "stats", component: Stats },
{ path: "settings", component: Settings }
]
}
]
});
Внутри компонента Dashboard можно использовать
useRoute для обработки вложенных маршрутов:
function Dashboard() {
const { route } = useRoute();
return html`
<aside>
<a href="/dashboard/stats" onCl ick=${navigate}>Статистика</a>
<a href="/dashboard/settings" onCl ick=${navigate}>Настройки</a>
</aside>
<section>
${route.component && route.component()}
</section>
`;
}
Такой подход позволяет разделять ответственность между уровнями маршрутов и избегать монолитного кода.
Для улучшения производительности применяют динамический импорт компонентов на основе маршрута:
const routes = [
{
path: "/profile",
component: async () => {
const module = await import("./Profile.js");
return module.default;
}
}
];
Atomico корректно обрабатывает промис, ожидая загрузку компонента перед рендером. Это позволяет снижать первоначальный размер скриптов и ускорять загрузку страниц.
Для перехвата неизвестных путей используют fallback:
const { route } = useRoute({
routes,
fallback: NotFound
});
Компонент NotFound будет рендериться при попытке
перехода на URL, который не соответствует ни одному маршруту.
Atomico взаимодействует с History API, что обеспечивает корректную работу кнопок браузера «Назад» и «Вперед»:
window.addEventListener("popstate", () => {
route.update(window.location.pathname);
});
Это позволяет обновлять состояние приложения при навигации без перезагрузки страницы, сохраняя привычное поведение для пользователей.
Client-side навигация в Atomico легко интегрируется с глобальным или локальным состоянием:
import { useStore } from "atomico";
const store = useStore({ loggedIn: false });
function Login() {
const { route } = useRoute();
const login = () => {
store.loggedIn = true;
history.pushState({}, "", "/dashboard");
window.dispatchEvent(new Event("popstate"));
};
return html`<button onCl ick=${login}>Войти</button>`;
}
Это позволяет изменять маршруты в ответ на события состояния, создавать защищённые маршруты и управлять доступом к разделам приложения.
Применение client-side навигации с Atomico часто выглядит как сочетание трёх ключевых слоёв:
Такой подход обеспечивает быструю и отзывчивую работу интерфейса, позволяя строить одностраничные приложения с полной поддержкой динамического контента.