Директивы и условная отрисовка

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

  • if — условная отрисовка элемента;
  • each — повторение элементов на основе массива или объекта;
  • show / hide — управление видимостью элемента;
  • ref — создание ссылки на DOM-элемент;
  • on — привязка событий к элементам;
  • class / style — динамическое управление классами и стилями.

Каждая директива имеет строгую синтаксическую структуру, которая обеспечивает оптимизацию рендеринга и минимизацию обновлений DOM.


Условная отрисовка с if

Директива if позволяет отображать элемент только при выполнении определённого условия. Синтаксис прост:

<div if={isVisible}>
  Контент отображается, если isVisible = true
</div>

Особенности работы if:

  • Элемент полностью создаётся и уничтожается в DOM при изменении условия.
  • Можно использовать else для альтернативного контента:
<div if={isLoggedIn}>
  Добро пожаловать!
</div>
<div else>
  Пожалуйста, войдите в систему.
</div>
  • Для сложных условий можно применять логические операторы прямо внутри фигурных скобок:
<div if={user.age > 18 && user.active}>
  Доступ разрешён
</div>

Использование if важно для случаев, когда элемент содержит сложный внутренний DOM или тяжелые компоненты — это снижает нагрузку на браузер.


Повторение элементов с each

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

<ul>
  <li each={item, index in items}>{item.name} — {index}</li>
</ul>

Пояснения:

  • item — текущий элемент массива;
  • index — порядковый номер элемента;
  • items — массив данных.

Особенности:

  • При изменении массива Riot.js автоматически добавляет, удаляет или перемещает элементы DOM.
  • Можно использовать объекты:
<li each={value, key in user.roles}>{key}: {value}</li>
  • В сочетании с if можно создавать фильтруемые списки:
<li each={task in tasks} if={task.completed}>{task.title}</li>

Управление видимостью: show и hide

В отличие от if, директивы show и hide не удаляют элемент из DOM, а изменяют его CSS-свойство display:

<div show={isActive}>Активный элемент</div>
<div hide={isActive}>Неактивный элемент</div>

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

  • Быстрая смена видимости без пересоздания элементов.
  • Удобно для анимаций и динамических интерфейсов.

Ссылки на элементы с ref

Директива ref позволяет сохранить ссылку на DOM-элемент для дальнейшего использования в скриптах компонента:

<input ref="usernameInput">

Доступ к элементу:

this.usernameInput.focus()

Особенности:

  • ref работает только внутри компонента.
  • Ссылки обновляются автоматически при рендеринге и удалении элементов.

Привязка событий: on

Директива on используется для обработки событий:

<button onCl ick={handleClick}>Нажми меня</button>

Особенности:

  • Поддерживаются все стандартные DOM-события (onMouseOver, onInput, onSubmit и т.д.).
  • Можно передавать аргументы в обработчик через стрелочные функции:
<button onCl ick={() => selectItem(item.id)}>Выбрать</button>
  • Riot.js обеспечивает автоматическое удаление обработчиков при уничтожении компонента.

Динамические классы и стили

Для управления классами и стилями используются директивы class и style:

<div class={isActive ? 'active' : 'inactive'}>Состояние элемента</div>
<div style={`color: ${textColor}; background: ${bgColor}`}>Текст с динамическим стилем</div>

Особенности:

  • Поддержка объектного синтаксиса для классов:
<div class={{active: isActive, disabled: isDisabled}}>Текст</div>
  • Стиль обновляется автоматически при изменении переменных компонента.

Сочетание директив для сложных интерфейсов

Часто используется комбинация нескольких директив:

<ul>
  <li each={task in tasks} if={!task.completed} class={{urgent: task.priority === 'high'}}>
    {task.title}
    <button onCl ick={() => completeTask(task.id)}>Завершить</button>
  </li>
</ul>

Здесь:

  • each создаёт список задач;
  • if фильтрует только незавершённые задачи;
  • class добавляет класс urgent для задач с высокой приоритетностью;
  • onClick привязывает действие к кнопке.

Такое сочетание позволяет строить динамичные, отзывчивые интерфейсы с минимальным количеством кода.


Важные нюансы

  • Использование if и each вместе может вызвать непредсказуемое поведение, если элемент часто создаётся и уничтожается. В таких случаях рекомендуется оптимизировать структуру данных.
  • Riot.js автоматически управляет жизненным циклом элементов, но слишком частые изменения массивов могут снижать производительность.
  • Для сложных компонентов лучше использовать комбинацию if и show, чтобы избегать постоянного пересоздания DOM-узлов.