Использование в разных фреймворках

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


Интеграция с React

Haunted легко взаимодействует с React благодаря своей схожести с концепцией хуков.

Создание Haunted-компонента:

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

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));

Использование внутри React-компонента:

import React from 'react';

function App() {
  return (
    <div>
      <my-counter></my-counter>
    </div>
  );
}

export default App;

Ключевой момент — Haunted-компонент определяется как стандартный веб-компонент через customElements.define. React просто рендерит его как обычный DOM-элемент. При этом состояние компонента полностью изолировано.


Интеграция с Angular

Angular поддерживает веб-компоненты через CUSTOM_ELEMENTS_SCHEMA, что позволяет использовать Haunted-компоненты без дополнительных обёрток.

Регистрация схемы в модуле:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import './my-counter.js'; // импорт Haunted-компонента

@NgModule({
  declarations: [],
  imports: [BrowserModule],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  bootstrap: []
})
export class AppModule {}

Использование в шаблоне:

<my-counter></my-counter>

Angular корректно обрабатывает такие элементы, а Haunted-компонент управляет своим состоянием самостоятельно.


Интеграция с Vue

Vue также поддерживает кастомные элементы. Для использования Haunted-компонентов достаточно зарегистрировать их как обычные HTML-теги:

import { createApp } from 'vue';
import './my-counter.js';

const app = createApp({
  template: `<my-counter></my-counter>`
});

app.mount('#app');

Vue игнорирует Shadow DOM и внутреннее состояние Haunted-компонента, позволяя ему полностью автономно управлять интерфейсом. При необходимости можно передавать атрибуты или слушать события:

<my-counter count="5" @change="onCountChange"></my-counter>

Использование с Vanilla JS

Haunted особенно полезен в проектах без фреймворков, где важна реактивность без лишнего веса. Пример:

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

function TodoList() {
  const [todos, setTodos] = useState([]);
  let input;

  const addTodo = () => {
    if (input.value) {
      setTodos([...todos, input.value]);
      input.value = '';
    }
  };

  return html`
    <div>
      <input placeholder="Новая задача" ${ref(input)} />
      <button @click=${addTodo}>Добавить</button>
      <ul>
        ${todos.map(todo => html`<li>${todo}</li>`)}
      </ul>
    </div>
  `;
}

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

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


Обработка событий и передача данных

Haunted-компоненты могут генерировать и слушать события, что облегчает взаимодействие с другими фреймворками:

const handleClick = () => {
  const event = new CustomEvent('increment', { detail: count });
  this.dispatchEvent(event);
};

При интеграции с Angular, React или Vue можно подписываться на эти события стандартными способами через атрибуты или слушатели событий.


Плюсы использования Haunted в разных фреймворках

  • Универсальность: один компонент может использоваться в React, Angular, Vue и чистом JS.
  • Изолированное состояние: компоненты не зависят от глобального состояния фреймворка.
  • Малый размер: библиотека минимальна по объёму, не требует виртуального DOM.
  • Совместимость с Shadow DOM: встроенная поддержка инкапсуляции стилей.
  • Лёгкая интеграция событий: CustomEvent позволяет легко связывать компоненты между собой.

Рекомендации по архитектуре

  • Для крупных приложений стоит создавать Haunted-компоненты модульно, чтобы их можно было импортировать в разные проекты без изменений.
  • Использовать сложные хуки (useEffect, useReducer) для управления побочными эффектами и более сложным состоянием.
  • Если проект построен на фреймворке, Haunted-компоненты рекомендуется использовать для изолированных интерактивных виджетов, чтобы не нарушать архитектуру приложения.

Haunted сочетает в себе реактивность и лёгкость веб-компонентов, обеспечивая универсальный способ создавать переиспользуемые интерфейсы, которые можно интегрировать практически в любой стек фронтенда.