Инструменты разработчика

Haunted — это библиотека для создания веб-компонентов на основе реактивного подхода в JavaScript, построенная поверх стандартов Web Components. Для работы с Haunted достаточно подключить его через npm или использовать CDN.

Через npm:

npm install haunted

И подключение в модуле:

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

Через CDN:

<script type="module">
  import { html, component, useState, useEffect } from 'https://unpkg.com/haunted/haunted.js?module';
</script>

Haunted не требует фреймворка или сборщика, его можно использовать с чистым HTML и JavaScript.


Основы компонентов Haunted

В Haunted компонент создаётся функцией, которая возвращает шаблон на основе html-тегов. Основные элементы:

  • component — регистрация функции как веб-компонента.
  • html — создание шаблонов с реактивной привязкой.
  • useState — управление состоянием внутри компонента.
  • useEffect — побочные эффекты, аналогичные React.

Пример простого компонента:

function Counter() {
  const [count, setCount] = useState(0);

  return html`
    <div>
      <p>Счётчик: ${count}</p>
      <button @click=${() => setCount(count + 1)}>Увеличить</button>
    </div>
  `;
}

customElements.define('my-counter', component(Counter));

Ключевой момент: любое изменение состояния через setCount автоматически перерисовывает шаблон.


Состояние и эффекты

useState

useState возвращает массив из двух элементов: текущего значения и функции для его обновления. Используется для локального состояния компонента. Можно создавать несколько состояний:

const [name, setName] = useState('Иван');
const [age, setAge] = useState(30);

Изменение любого из этих состояний вызывает реактивное обновление компонента.

useEffect

useEffect управляет побочными эффектами. Функция выполняется после рендера компонента. Можно контролировать частоту выполнения через массив зависимостей:

useEffect(() => {
  console.log('Компонент обновлён');
}, [count]); // вызов только при изменении count

Если массив зависимостей пуст, эффект выполняется один раз при монтировании компонента.


Работа с атрибутами и свойствами

В Haunted можно синхронизировать свойства компонента с его HTML-атрибутами. Это делается через объект observedAttributes и привязку в функции компонента:

function Greeting({ name }) {
  return html`<p>Привет, ${name}!</p>`;
}

customElements.define('my-greeting', component(Greeting, { observedAttributes: ['name'] }));

Атрибут name автоматически передаётся в компонент как свойство.


События и реактивные шаблоны

Haunted поддерживает обработку событий с использованием синтаксиса @событие:

html`<button @click=${handleClick}>Нажми</button>`

Функция handleClick вызывается при срабатывании события. Можно использовать стрелочные функции для передачи аргументов:

html`<button @click=${() => setCount(count + 1)}>Увеличить</button>`

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

html`${count > 0 ? html`<p>Счётчик больше нуля</p>` : html`<p>Счётчик равен нулю</p>`}`

Для повторяющихся элементов удобно использовать map:

html`
  <ul>
    ${items.map(item => html`<li>${item}</li>`)}
  </ul>
`

Подключение сторонних библиотек

Haunted позволяет интегрироваться с любыми JS-библиотеками. Например, для использования библиотек анимации можно обернуть их вызовы в useEffect:

useEffect(() => {
  const anim = new SomeAnimationLibrary(elementRef.current);
  anim.start();
  return () => anim.stop(); // очистка при размонтировании
}, []);

Это обеспечивает совместимость реактивного подхода с любыми внешними инструментами.


DevTools и отладка

Haunted работает с обычными браузерными DevTools. Для отладки:

  • Просмотр компонентов: в Elements можно увидеть кастомные элементы <my-counter>.
  • Отслеживание состояния: при изменении useState шаблон автоматически обновляется, что позволяет тестировать реактивность напрямую.
  • Консоль: console.log в эффектах и обработчиках событий удобно использовать для мониторинга состояния и жизненного цикла.

Совет: удобно использовать WeakMap для хранения приватных данных компонента без засорения DOM.


Продвинутые возможности

useReducer

Для сложной логики состояния применяют useReducer, аналогичный React:

function reducer(state, action) {
  switch(action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'decrement': return { count: state.count - 1 };
    default: return state;
  }
}

const [state, dispatch] = useReducer(reducer, { count: 0 });

useRef

useRef позволяет сохранять ссылку на DOM-элемент или значение между рендерами:

const inputRef = useRef();
html`<input type="text" ref=${inputRef}>`;

Это упрощает работу с нативным DOM.


Совместное использование с Lit и другими шаблонизаторами

Haunted совместим с Lit-html, так как использует тот же синтаксис html. Можно комбинировать Haunted с Lit для более сложных интерфейсов, используя шаблоны и директивы Lit.

import { html as litHtml } from 'lit-html';

function MixedComponent() {
  return html`
    ${litHtml`<p>Комбинированный шаблон</p>`}
  `;
}

Такой подход позволяет использовать преимущества обеих библиотек, сохраняя реактивность Haunted.


Haunted предоставляет мощный и минималистичный инструмент для разработки реактивных веб-компонентов, где управление состоянием, побочные эффекты и работа с DOM интегрированы через понятные и гибкие хуки.