Декораторы и их использование

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

Декоратор @property

@property является основным декоратором для объявления реактивных свойств компонента. Он автоматически создаёт геттеры и сеттеры, которые отслеживают изменения значения и инициируют перерисовку компонента.

Синтаксис:

import { LitElement, html } from 'lit';
import { property } from 'lit/decorators.js';

class MyElement extends LitElement {
  @property({ type: String })
  name = 'Default';

  render() {
    return html`<p>${this.name}</p>`;
  }
}

customElements.define('my-element', MyElement);

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

  • type — определяет тип свойства (String, Number, Boolean, Array, Object). Lit автоматически преобразует значение атрибута в указанный тип.
  • attribute — имя HTML-атрибута, связанного со свойством. По умолчанию совпадает с именем свойства в формате kebab-case.
  • reflect — если true, значение свойства автоматически синхронизируется с атрибутом HTML.
@property({ type: Boolean, reflect: true })
isVisible = false;

Декоратор @state

@state используется для создания приватных реактивных свойств, которые не должны отражаться в атрибутах HTML. Такие свойства удобны для внутреннего состояния компонента.

import { state } from 'lit/decorators.js';

class CounterElement extends LitElement {
  @state()
  privateCount = 0;

  increment() {
    this.privateCount++;
  }

  render() {
    return html`<p>Count: ${this.privateCount}</p>`;
  }
}

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

  • Свойство остаётся реактивным, но не создаёт HTML-атрибут.
  • Используется для внутренних вычислений и временного состояния.

Декоратор @query и @queryAll

Эти декораторы позволяют получать доступ к элементам DOM внутри компонента без явного поиска через this.shadowRoot.querySelector.

import { query, queryAll } from 'lit/decorators.js';

class MyForm extends LitElement {
  @query('#input')
  inputElement;

  @queryAll('button')
  buttons;

  focusInput() {
    this.inputElement.focus();
  }
}

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

  • @query возвращает первый элемент, соответствующий селектору.
  • @queryAll возвращает массив всех элементов, подходящих под селектор.
  • Применяются для работы с локальным DOM компонента и упрощают манипуляции с элементами.

Декоратор @eventOptions

Позволяет задавать параметры событий, такие как capture, once, passive при использовании методов, обрабатывающих события.

import { eventOptions } from 'lit/decorators.js';

class MyButton extends LitElement {
  @eventOptions({ capture: true, once: true })
  handleClick(event) {
    console.log('Clicked once with capture:', event);
  }

  render() {
    return html`<button @click=${this.handleClick}>Click me</button>`;
  }
}

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

  • Удобно для точной настройки поведения слушателей событий.
  • Может комбинироваться с другими декораторами для методов компонента.

Комбинирование декораторов

Декораторы можно комбинировать для более гибкой декларации свойств и методов. Например, свойство может быть реактивным, отражаться в атрибут и оставаться приватным, в зависимости от нужд:

class CustomInput extends LitElement {
  @property({ type: String, reflect: true })
  value = '';

  @state()
  internalFlag = false;
}

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

  • Использовать @property для публичных свойств, взаимодействующих с атрибутами HTML.
  • Использовать @state для внутреннего состояния, не предназначенного для внешнего доступа.
  • Применять @query и @queryAll для обращения к элементам Shadow DOM без лишнего кода.
  • @eventOptions помогает точно настраивать обработку событий и снижает количество ошибок при сложной логике.

Декораторы в Lit делают код компонентов лаконичным, выразительным и легко расширяемым, обеспечивая при этом высокую производительность реактивного обновления интерфейса.