Организация кода

Unpoly — это прогрессивная библиотека для обновления частей страницы без полной перезагрузки. В отличие от классических SPA-фреймворков, Unpoly позволяет интегрировать динамическое поведение в существующие серверные шаблоны с минимальными изменениями. Организация кода в Unpoly строится вокруг селекторов, событий и слоёв обновления, что влияет на читаемость и поддержку приложения.

Структура обновлений и фрагментов

В Unpoly любое обновление страницы основано на фрагментах HTML, которые обозначаются с помощью атрибута up-target. Основные элементы:

  • Цель обновления (up-target) — определяет контейнер, который будет заменён содержимым ответа.
  • Источник запроса (up-href или form с up-submit) — URL, с которого берётся HTML.
  • Анимации и эффекты (up-transition) — позволяют задавать визуальные переходы между старым и новым содержимым.

Пример корректной структуры кнопки для обновления списка без перезагрузки:

<button up-target="#user-list" up-href="/users" up-transition="fade">
  Обновить список
</button>
<div id="user-list">
  <!-- Контент будет заменён -->
</div>

События и их обработка

Unpoly использует систему событий, позволяющую отделить логику взаимодействия от HTML. Основные события:

  • up:click — срабатывает при клике на элемент с up-href.
  • up:form:submit — срабатывает перед отправкой формы через AJAX.
  • up:fragment:loaded — вызывается после обновления фрагмента на странице.

События можно назначать через up.on() для глобальной обработки:

up.on('up:fragment:loaded', '#user-list', (event) => {
  console.log('Список пользователей обновлён', event.fragment);
});

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

Декларативное и программное обновление

Unpoly поддерживает два подхода к обновлению фрагментов:

  1. Декларативный — через атрибуты HTML (up-target, up-href, up-submit), что снижает количество JS-кода и облегчает поддержку серверного рендеринга.
  2. Программный — через API up.request() для более сложных сценариев, например, когда нужно динамически менять параметры запроса:
up.request('/users', {
  target: '#user-list',
  method: 'GET',
  transition: 'fade'
}).then(response => {
  console.log('Фрагмент обновлён программно');
});

Программный подход полезен для компонентов, которые формируют параметры запроса на основе состояния JavaScript.

Организация JavaScript-кода

Для больших приложений рекомендуется разделять JS по фрагментам или модулям компонентов, где каждый модуль отвечает за конкретный контейнер (up-target).

Структура модуля фрагмента:

// user_list.js
export default function initUserList(fragment) {
  const refreshButton = fragment.querySelector('[data-refresh]');
  if (refreshButton) {
    refreshButton.addEventListener('click', () => {
      up.request('/users', { target: '#user-list', transition: 'fade' });
    });
  }
}

Подключение модуля через событие up:fragment:loaded:

import initUserList from './user_list.js';

up.on('up:fragment:loaded', '#user-list', (event) => {
  initUserList(event.fragment);
});

Такой подход обеспечивает:

  • Изоляцию кода — модули не зависят от глобальных переменных.
  • Повторное использование — один и тот же модуль можно подключать к разным страницам.
  • Легкость тестирования — каждая функция привязана к конкретному DOM-фрагменту.

Работа с формами и валидацией

Unpoly облегчает обработку форм без полной перезагрузки. Основные элементы:

  • Атрибут up-submit вместо стандартного <form> позволяет отправлять форму через AJAX.
  • up-target определяет, какой фрагмент заменяется после ответа.
  • Поддерживаются обычные события валидации (up:form:submit, up:form:submitted).

Пример:

<form up-submit="#user-list" action="/users" method="POST">
  <input type="text" name="name">
  <button type="submit">Добавить</button>
</form>
<div id="user-list"></div>

В JavaScript можно подписаться на событие отправки формы:

up.on('up:form:submitted', '#user-list', (event) => {
  if (event.success) {
    console.log('Форма успешно отправлена');
  } else {
    console.warn('Ошибка при отправке формы');
  }
});

Оптимизация и поддержка кода

  • Фрагменты должны быть минимальными: заменять только нужные части страницы.
  • Код должен быть модульным: каждый фрагмент имеет собственный JS-модуль.
  • События используют делегирование: up.on('event', selector, handler) вместо прямой привязки к элементам.
  • Логика разделена на уровни: декларативные атрибуты для базового поведения, события для кастомной логики, программный API для динамических сценариев.

Организация кода таким образом делает приложения на Unpoly поддерживаемыми, легко расширяемыми и совместимыми с серверными шаблонами.