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

Условный рендеринг в Lit позволяет управлять отображением элементов на странице в зависимости от состояния компонента. В основе этого механизма лежит директива ifDefined и встроенные функции шаблонов, такие как тернарный оператор и директива nothing.

Использование тернарного оператора

Самый простой способ управлять содержимым — применять тернарный оператор внутри шаблона:

import { LitElement, html, css } from 'lit';

class ConditionalRenderExample extends LitElement {
  static properties = {
    isVisible: { type: Boolean }
  };

  constructor() {
    super();
    this.isVisible = true;
  }

  render() {
    return html`
      <div>
        ${this.isVisible ? html`<p>Элемент видим</p>` : html``}
      </div>
      <button @click="${() => this.isVisible = !this.isVisible}">
        Переключить видимость
      </button>
    `;
  }
}

customElements.define('conditional-render-example', ConditionalRenderExample);

В данном примере <p> отображается только при значении isVisible = true. Если isVisible становится false, Lit заменяет содержимое на пустой шаблон `html```, что предотвращает рендеринг элемента.

Директива nothing

Директива nothing из пакета lit позволяет явно указать отсутствие содержимого в шаблоне:

import { nothing } from 'lit';

render() {
  return html`
    <div>
      ${this.isVisible ? html`<p>Элемент видим</p>` : nothing}
    </div>
  `;
}

Использование nothing более семантически корректно и оптимизировано для рендеринга, так как Lit понимает, что элемент полностью отсутствует.

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

Для нескольких вариантов можно применять цепочку тернарных операторов или создавать вспомогательные методы:

render() {
  return html`
    ${this.status === 'loading' ? html`<p>Загрузка...</p>` :
      this.status === 'success' ? html`<p>Данные загружены</p>` :
      html`<p>Ошибка загрузки</p>`}
  `;
}

Для улучшения читаемости рекомендуется вынести рендеринг в отдельный метод:

renderStatus() {
  switch(this.status) {
    case 'loading': return html`<p>Загрузка...</p>`;
    case 'success': return html`<p>Данные загружены</p>`;
    default: return html`<p>Ошибка загрузки</p>`;
  }
}

render() {
  return html`
    <div>${this.renderStatus()}</div>
  `;
}

Директива ifDefined

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

import { ifDefined } from 'lit/directives/if-defined.js';

render() {
  const title = this.isVisible ? 'Элемент активен' : undefined;
  return html`
    <div title=${ifDefined(title)}>Контент блока</div>
  `;
}

Если значение undefined, атрибут не добавляется в DOM, что позволяет избегать ненужных пустых атрибутов.

Комбинация с массивами и map

Для динамического отображения списков с условием можно комбинировать тернарный оператор и map:

render() {
  const items = ['Первый', 'Второй', 'Третий'];
  return html`
    <ul>
      ${items.map(item => this.isVisible ? html`<li>${item}</li>` : nothing)}
    </ul>
  `;
}

Каждый элемент массива рендерится только если условие истинно, иначе используется nothing.

Оптимизация условного рендеринга

  • Минимизация вложенности тернарных операторов повышает читаемость кода.
  • Вынесение логики в методы упрощает тестирование и повторное использование.
  • Использование nothing вместо пустых шаблонов позволяет Lit оптимально обновлять DOM.
  • Условное применение атрибутов через ifDefined предотвращает рендеринг лишних атрибутов и упрощает работу с динамическими свойствами элементов.

Практические советы

  • При сложных условиях стоит использовать отдельные функции рендеринга, чтобы шаблон оставался компактным.
  • Для больших массивов данных с условным рендерингом эффективнее фильтровать данные заранее, чем возвращать nothing для каждого элемента.
  • Условный рендеринг тесно интегрирован с реактивными свойствами Lit, поэтому любое изменение состояния автоматически обновляет DOM без ручного вмешательства.

Условный рендеринг является основой создания динамических интерфейсов в Lit. Правильное использование директив и реактивных свойств обеспечивает чистый, производительный и легко поддерживаемый код.