Интеграция сторонних роутеров

Slim.js предоставляет минималистичный, компонентно-ориентированный подход к разработке веб-приложений. Его встроенный роутинг подходит для большинства задач, однако для сложных приложений часто требуется интеграция сторонних роутеров, таких как Navigo, Page.js или Director. Slim.js не накладывает жестких ограничений, что позволяет гибко сочетать внутренние компоненты и внешние маршрутизаторы.

Архитектура маршрутизации в Slim.js

В Slim.js компоненты могут управлять своим состоянием и визуализацией независимо, но маршрутизация обычно осуществляется через глобальные события или через управление состоянием приложения. Основные моменты:

  • Slim.Router — встроенный базовый роутер, обеспечивающий простую привязку URL к методам компонента.
  • Компонент как view — каждый компонент может выступать отдельным представлением, которое отображается при изменении маршрута.
  • События для синхронизации — внешние роутеры уведомляют компоненты о смене маршрута через события или коллбэки.

Подключение внешнего роутера

Для интеграции стороннего роутера важно создать прослойку, которая синхронизирует маршруты внешнего роутера с состоянием Slim.js. Рассмотрим пример с Navigo:

import Navigo from 'navigo';
import { Slim } from 'slim-js';

const router = new Navigo('/', { hash: true });

class AppComponent extends Slim {
  get useShadow() {
    return true;
  }

  template() {
    return `
      <div id="view"></div>
    `;
  }

  onRouteChange(viewName) {
    this.shadowRoot.getElementById('view').innerHTML = `<${viewName}></${viewName}>`;
  }
}

const app = new AppComponent();
document.body.appendChild(app);

// Настройка маршрутов
router.on({
  '/home': () => app.onRouteChange('home-component'),
  '/about': () => app.onRouteChange('about-component'),
  '/contact': () => app.onRouteChange('contact-component')
}).resolve();

Ключевые моменты интеграции:

  • Внешний роутер управляет URL и вызывает методы Slim.js-компонента.
  • Slim.js-компонент отвечает за рендеринг соответствующего представления.
  • При необходимости можно использовать Shadow DOM, чтобы изолировать стили компонентов.

Обработка динамических маршрутов

Для маршрутов с параметрами, таких как /user/:id, требуется передача параметров внутрь компонентов. В Navigo это выглядит так:

router.on('/user/:id', (params) => {
  app.onRouteChange('user-component', params.id);
});

В Slim.js:

class UserComponent extends Slim {
  set userId(id) {
    this._userId = id;
    this.renderUser();
  }

  renderUser() {
    this.innerHTML = `<p>Пользователь с ID: ${this._userId}</p>`;
  }
}

Такой подход позволяет динамически подставлять данные в компоненты при смене маршрута, сохраняя реактивность Slim.js.

Синхронизация состояния

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

  • Глобальный стор — объект или класс для хранения состояния приложения.
  • Подписка на события роутера — позволяет компонентам реагировать на смену маршрута.
  • Методы обновления компонентов — вызов setState или пользовательских методов для обновления интерфейса.

Пример:

class AppState {
  constructor() {
    this.currentRoute = '';
    this.listeners = [];
  }

  setRoute(route) {
    this.currentRoute = route;
    this.listeners.forEach(cb => cb(route));
  }

  subscribe(cb) {
    this.listeners.push(cb);
  }
}

const appState = new AppState();

router.on({
  '/home': () => appState.setRoute('home-component'),
  '/about': () => appState.setRoute('about-component')
});

appState.subscribe((route) => {
  app.onRouteChange(route);
});

Интеграция нескольких роутеров

В проектах с микрофронтендами может понадобиться использование нескольких роутеров одновременно. В Slim.js это реализуется через делегирование маршрутов:

  • Каждый роутер отвечает за свою часть URL (/admin/*, /user/*).
  • Основной компонент подписан на изменения всех роутеров и обновляет видимые компоненты.
  • Для предотвращения конфликтов важно согласовать формат URL и методы уведомления.

Пример делегирования:

adminRouter.on('/admin/:page', (params) => app.onRouteChange('admin-component', params.page));
userRouter.on('/user/:id', (params) => app.onRouteChange('user-component', params.id));

Работа с навигацией и переходами

Для плавной навигации рекомендуется:

  • Использовать методы router.navigate() или аналогичные для программной смены маршрута.
  • Избегать прямого изменения window.location, чтобы не ломать реактивность компонентов.
  • Добавлять обработку ошибок при неизвестных маршрутах и использовать fallback-компоненты.

Настройка SEO и SSR

Slim.js с внешними роутерами позволяет реализовать серверный рендеринг и SEO-оптимизацию через:

  • Генерацию HTML на сервере с нужным компонентом.
  • Настройку роутера для корректной работы с ссылками и pushState.
  • Обновление метатегов динамически при смене маршрута.

Пример динамического обновления заголовка:

appState.subscribe((route) => {
  document.title = `Страница - ${route.replace('-component', '')}`;
});

Практические рекомендации

  • Изолировать логику роутера от компонентов, чтобы компоненты оставались переиспользуемыми.
  • Использовать подписку на глобальное состояние, чтобы избежать прямых вызовов роутера внутри каждого компонента.
  • Обрабатывать динамические параметры и fallback для корректной работы всех сценариев.
  • Тестировать маршруты на разных браузерах, особенно при использовании hash и pushState.

Интеграция сторонних роутеров в Slim.js обеспечивает мощную гибкость, позволяя строить масштабируемые SPA с минимальными ограничениями и поддержкой сложных сценариев маршрутизации.