Программная навигация

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


Создание маршрутов и использование Router

Riot.js не включает встроенный полноценный роутер, однако стандартной практикой является использование сторонних библиотек, таких как riot-route или простых пользовательских решений. Для начала работы с маршрутизацией подключается route:

import route from 'riot-route'

Маршруты задаются с помощью метода route():

route('/', () => showComponent('home'))
route('/about', () => showComponent('about'))
route('/contact', () => showComponent('contact'))

Пояснение:

  • Первый аргумент — путь, который отслеживается.
  • Второй аргумент — функция, выполняемая при совпадении пути. В ней можно обновлять состояние приложения или подгружать соответствующий компонент.

Запуск роутинга осуществляется вызовом:

route.start(true)

Флаг true позволяет обработать текущий URL при инициализации.


Динамическая загрузка компонентов

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

function showComponent(name) {
  import(`./components/${name}.riot`).then(module => {
    const component = module.default
    document.getElementById('app').innerHTML = ''
    component.mount('#app')
  })
}

Особенности подхода:

  • Используется динамический import, что уменьшает начальный размер бандла.
  • Каждый компонент монтируется в контейнер с id="app", заменяя старое содержимое.
  • Поддерживается lazy loading — компоненты подгружаются только при необходимости.

Работа с параметрами маршрута

Маршруты могут содержать динамические параметры. Riot.js позволяет извлекать их через роутер:

route('/user/:id', (id) => {
  showComponent('user', { id })
})

Передача параметров в компонент осуществляется через объект:

function showComponent(name, props = {}) {
  import(`./components/${name}.riot`).then(module => {
    const component = module.default
    document.getElementById('app').innerHTML = ''
    component.mount('#app', props)
  })
}

Внутри компонента props доступны для рендеринга и логики:

<user>
  <p>User ID: {props.id}</p>
</user>

Управление историей и переходами

Программная навигация должна учитывать историю браузера для корректной работы кнопок «Назад» и «Вперед». Riot.js совместно с роутером позволяет использовать методы route() для навигации:

// Переход к маршруту программно
route('/about')

// Возврат к предыдущему маршруту
window.history.back()

Использование роутера с pushState обеспечивает плавные переходы без перезагрузки страницы и сохраняет историю в браузере.


Состояние и навигация

Программная навигация тесно связана с состоянием приложения. Чаще всего создаются глобальные хранилища или минимальные state-объекты:

const store = {
  currentUser: null,
  currentPage: 'home'
}

function showComponent(name, props = {}) {
  store.currentPage = name
  import(`./components/${name}.riot`).then(module => {
    const component = module.default
    document.getElementById('app').innerHTML = ''
    component.mount('#app', { ...props, store })
  })
}

Преимущества подхода:

  • Компоненты получают доступ к глобальному состоянию.
  • Легко реализуются условные переходы (например, проверка авторизации перед показом страницы).
  • Обновление состояния автоматически отражается на текущем компоненте.

Анимация и переходы между страницами

Для более сложных интерфейсов можно подключать анимации при смене компонентов. Riot.js позволяет управлять жизненным циклом компонентов, что упрощает внедрение эффектов:

function showComponent(name, props = {}) {
  const app = document.getElementById('app')
  app.classList.add('fade-out')

  setTimeout(() => {
    app.innerHTML = ''
    import(`./components/${name}.riot`).then(module => {
      const component = module.default
      component.mount('#app', props)
      app.classList.remove('fade-out')
      app.classList.add('fade-in')
    })
  }, 300)
}

Пояснение:

  • Используется класс CSS fade-out для плавного исчезновения.
  • После подгрузки компонента применяется класс fade-in.
  • Такой подход обеспечивает визуальную целостность при программной навигации.

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

Программная навигация в Riot.js может сочетаться с серверными запросами. Часто при переходе на новую страницу требуется подгрузить данные через API:

route('/posts/:id', async (id) => {
  const data = await fetch(`/api/posts/${id}`).then(res => res.json())
  showComponent('post', { post: data })
})

Преимущества интеграции:

  • Минимизируется перезагрузка страницы.
  • Позволяет строить SPA с полноценным взаимодействием с сервером.
  • Упрощается обработка ошибок и состояние загрузки компонентов.

Программная навигация в Riot.js сочетает лёгкость фреймворка с гибкостью маршрутизации и динамической загрузки компонентов. Использование роутеров, управление состоянием и анимации позволяют строить удобные и отзывчивые интерфейсы без перегруженного кода.