Условный рендеринг

Haunted — это минималистичная библиотека для создания веб-компонентов с использованием реактивного подхода, вдохновлённого React Hooks. Одной из ключевых возможностей при построении интерфейсов является условный рендеринг, позволяющий изменять отображение DOM в зависимости от состояния компонента.

В Haunted условный рендеринг достигается через стандартные механизмы Jav * aScript: тернарные операторы, логические выражения и функции, возвращающие шаблоны.


Тернарный оператор

Тернарный оператор является самым распространённым способом управлять условным отображением. В Haunted он используется внутри шаблонов, создаваемых с помощью html из haunted.

import { html, component } from 'haunted';
import { useState } from 'haunted';

function UserStatus() {
  const [loggedIn, setLoggedIn] = useState(false);

  return html`
    <div>
      ${loggedIn 
        ? html`<p>Пользователь вошёл в систему</p>`
        : html`<p>Пользователь не авторизован</p>`}
      <button @click=${() => setLoggedIn(!loggedIn)}>
        ${loggedIn ? 'Выйти' : 'Войти'}
      </button>
    </div>
  `;
}

customElements.define('user-status', component(UserStatus));

Ключевые моменты:

  • Шаблон внутри ${} может возвращать другой шаблон `html```, создавая вложенные структуры.
  • Состояние loggedIn управляется через useState, что обеспечивает реактивное обновление DOM при изменении значения.

Логические выражения

Для простых условий можно использовать логические операторы && и ||. Они позволяют сократить код, когда нужно отобразить элемент только при истинном значении условия.

function Notification({ message }) {
  return html`
    <div>
      ${message && html`<p>Новое уведомление: ${message}</p>`}
    </div>
  `;
}

customElements.define('notification-message', component(Notification));

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

  • Если message равно null или undefined, блок не рендерится.
  • Логический оператор удобно использовать для скрытия или отображения отдельных элементов без тернарного оператора.

Функции для условного рендеринга

Когда условия становятся сложными, логично выносить рендеринг в отдельные функции. Это повышает читаемость и упрощает поддержку кода.

function renderContent(type) {
  switch(type) {
    case 'loading':
      return html`<p>Загрузка...</p>`;
    case 'error':
      return html`<p>Произошла ошибка</p>`;
    case 'success':
      return html`<p>Данные успешно загружены</p>`;
    default:
      return html``;
  }
}

function DataStatus() {
  const [status, setStatus] = useState('loading');

  return html`
    <div>
      ${renderContent(status)}
      <button @click=${() => setStatus('success')}>Загрузить</button>
    </div>
  `;
}

customElements.define('data-status', component(DataStatus));

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

  • Чёткая логика условий отделена от основного шаблона.
  • Легко расширять, добавляя новые состояния.

Условный рендеринг нескольких элементов

Haunted позволяет рендерить несколько элементов одновременно с помощью массивов или `html`` шаблонов внутри тернарного оператора.

function TodoList({ todos }) {
  return html`
    <ul>
      ${todos.length === 0 
        ? html`<li>Список пуст</li>` 
        : todos.map(todo => html`<li>${todo}</li>`)}
    </ul>
  `;
}

customElements.define('todo-list', component(TodoList));

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

  • Метод map используется для динамического создания элементов списка.
  • Пустой массив обрабатывается отдельным условием.

Динамическое отображение атрибутов

Условный рендеринг не ограничивается только содержимым. Атрибуты элементов также можно изменять динамически.

function Button({ disabled }) {
  return html`
    <button ?disabled=${disabled}>
      ${disabled ? 'Недоступно' : 'Нажми меня'}
    </button>
  `;
}

customElements.define('dynamic-button', component(Button));

Синтаксис ?attr=${value}:

  • Позволяет привязывать булевы значения к атрибутам HTML.
  • Атрибут добавляется только при истинном значении.

Важные рекомендации

  1. Минимизировать вложенность тернарных операторов. Слишком глубокие вложения ухудшают читаемость.
  2. Выносить сложную логику в отдельные функции. Это делает шаблоны проще и безопаснее.
  3. Использовать реактивные состояния через useState или useReducer. Это обеспечивает автоматическое обновление DOM при изменении данных.
  4. При рендеринге списков всегда использовать уникальные ключи, если элементы могут изменяться. Это предотвращает ненужные перерисовки.

Условный рендеринг в Haunted сочетает мощь реактивных хуков с лаконичностью шаблонов `html``. Тернарные операторы, логические выражения и функции позволяют гибко управлять отображением интерфейса, создавая динамичные и отзывчивые веб-компоненты.