Использование с Vue

Для начала работы с Universal Router в проекте на Vue необходимо установить библиотеку через npm или yarn:

npm install universal-router

или

yarn add universal-router

После установки создается основной маршрутный конфиг, представляющий собой массив объектов с ключами path и action. Каждый объект маршрута описывает соответствие URL и функцию обработки. В контексте Vue действие маршрута обычно возвращает компонент, который будет отображаться в корневом элементе приложения.

import UniversalRouter from 'universal-router';
import Home from './components/Home.vue';
import About from './components/About.vue';

const routes = [
  { path: '/', action: () => Home },
  { path: '/about', action: () => About },
];

const router = new UniversalRouter(routes);
export default router;

Интеграция с Vue

В Vue 3 можно интегрировать Universal Router через реактивное состояние. Создается реактивная переменная для текущего компонента и функция для изменения маршрута при изменении URL:

import { createApp, reactive, h } from 'vue';
import router from './router';

const state = reactive({ currentRoute: null });

async function navigate(path) {
  state.currentRoute = await router.resolve(path);
}

window.addEventListener('popstate', () => {
  navigate(window.location.pathname);
});

navigate(window.location.pathname);

createApp({
  render() {
    return h(state.currentRoute);
  }
}).mount('#app');

В этом примере каждый переход по URL обновляет state.currentRoute, что автоматически вызывает перерисовку компонента через реактивность Vue.

Работа с динамическими маршрутами

Universal Router поддерживает динамические сегменты в пути с помощью синтаксиса :param:

const routes = [
  { path: '/user/:id', action: ({ params }) => ({ component: User, props: { id: params.id } }) },
];

Динамические параметры передаются в функцию action через объект params. В Vue компонент можно передать эти параметры через props, что позволяет компоненту получать нужные данные напрямую.

Вложенные маршруты

Поддержка вложенных маршрутов реализуется с помощью массива children в объекте маршрута:

const routes = [
  {
    path: '/dashboard',
    action: () => Dashboard,
    children: [
      { path: 'stats', action: () => Stats },
      { path: 'settings', action: () => Settings }
    ]
  }
];

В этом случае URL /dashboard/stats активирует маршрут Stats, а /dashboard/settingsSettings. Universal Router автоматически строит иерархию маршрутов и передает их в resolve.

Навигация программно

Для изменения маршрута без перезагрузки страницы используется history.pushState или аналогичные методы. Универсальный роутер интегрируется с этим подходом через функцию навигации:

function goTo(path) {
  window.history.pushState(null, '', path);
  navigate(path);
}

Это позволяет создавать кнопки и ссылки с обработкой переходов на клиентской стороне, сохраняя работу реактивного состояния Vue.

Использование асинхронных действий

Маршруты могут возвращать промисы, что удобно для подгрузки компонентов или данных:

const routes = [
  { 
    path: '/posts/:id', 
    action: async ({ params }) => {
      const module = await import('./components/Post.vue');
      const data = await fetch(`/api/posts/${params.id}`).then(r => r.json());
      return { component: module.default, props: { post: data } };
    }
  }
];

Асинхронная функция action позволяет загружать компоненты по требованию и получать данные с сервера до отображения страницы, что повышает производительность и уменьшает время первой загрузки.

Хуки и middleware

Universal Router поддерживает middleware-подход через функцию resolve. Можно реализовать проверку прав доступа или глобальные действия перед рендерингом компонента:

const router = new UniversalRouter(routes, {
  resolveRoute(context, params) {
    if (context.route.meta?.requiresAuth && !isAuthenticated()) {
      return Login;
    }
    return context.route.action(context, params);
  }
});

Ключ meta используется для хранения дополнительной информации о маршруте, например, необходимости авторизации или роли пользователя.

Поддержка query-параметров

Query-параметры не являются частью пути, но доступны через объект query. Их можно извлечь из URL и передать в компонент:

function parseQuery(search) {
  return Object.fromEntries(new URLSearchParams(search));
}

window.addEventListener('popstate', () => {
  const query = parseQuery(window.location.search);
  navigate(window.location.pathname + window.location.search, { query });
});

В action query-параметры доступны для передачи в компонент, что позволяет управлять состоянием страницы без изменения маршрута.

Lazy-loading компонентов

Асинхронная загрузка компонентов повышает производительность крупных Vue-приложений:

const routes = [
  {
    path: '/lazy',
    action: async () => {
      const component = await import('./components/LazyComponent.vue');
      return component.default;
    }
  }
];

Совмещение lazy-loading с динамическими маршрутами и асинхронной загрузкой данных делает Universal Router гибким инструментом для современных SPA.

Управление состоянием маршрутов

Universal Router не хранит состояние истории или активного маршрута, это полностью контролируется приложением. Для интеграции с Vue можно использовать реактивные объекты, Vuex или Pinia:

import { reactive } from 'vue';
export const routeState = reactive({ current: null });

async function changeRoute(path) {
  routeState.current = await router.resolve(path);
}

Таким образом создается централизованное хранилище текущего маршрута, доступное во всех компонентах через реактивные ссылки.

Резюме по ключевым возможностям

  • Поддержка динамических и вложенных маршрутов.
  • Асинхронная загрузка компонентов и данных.
  • Middleware для авторизации и обработки маршрутов.
  • Полная интеграция с реактивностью Vue.
  • Возможность работы с query-параметрами и программной навигацией.

Universal Router предоставляет гибкую архитектуру для SPA на Vue, позволяя строить как простые маршруты, так и сложные многоуровневые структуры с асинхронными компонентами и динамическими параметрами.