Haunted — это библиотека для создания веб-компонентов на базе функциональных реактивных компонентов в стиле React, но с минимальным оверхедом. Одной из ключевых задач при работе с веб-компонентами является управление ссылками на DOM-элементы. В Haunted это реализуется через рефы и стандартные методы работы с Shadow DOM.
В Haunted используется хук useRef для создания ссылки на
DOM-элемент. С помощью этой ссылки можно напрямую взаимодействовать с
элементом: изменять его свойства, вызывать методы или подписываться на
события.
Пример создания рефа:
import { html, component, useRef } from 'haunted';
function MyComponent() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return html`
<input type="text" ref=${inputRef} />
<button @click=${focusInput}>Фокус на поле</button>
`;
}
customElements.define('my-component', component(MyComponent));
Пояснения:
useRef(null) создаёт объект с полем
current, которое хранит ссылку на DOM-элемент.ref=${inputRef} автоматически привязывает
DOM-элемент к свойству current.inputRef.current содержит актуальный
элемент <input>.В веб-компонентах с Shadow DOM использование
querySelector часто ограничено областью компонента. Ref в
Haunted позволяет:
Пример сравнения:
// Использование querySelector (менее безопасно в Shadow DOM)
const input = this.shadowRoot.querySelector('input');
// Использование ref (более безопасно)
const input = inputRef.current;
Ref обеспечивает безопасный доступ к элементу без необходимости учитывать Shadow DOM или уникальные селекторы.
Если нужно управлять коллекцией элементов, можно использовать массив рефов. Это удобно для динамических списков или повторяющихся компонентов.
function ListComponent({ items }) {
const refs = items.map(() => useRef(null));
const highlightAll = () => {
refs.forEach(r => {
if (r.current) r.current.style.backgroundColor = 'yellow';
});
};
return html`
<ul>
${items.map((item, index) => html`
<li ref=${refs[index]}>${item}</li>
`)}
</ul>
<button @click=${highlightAll}>Выделить все</button>
`;
}
Ключевые моменты:
refs[index].current указывает на
конкретный <li> элемент.Иногда требуется выполнить действие после монтирования компонента или
после обновления DOM. В Haunted для этого используется
useEffect.
import { useEffect } from 'haunted';
function FocusComponent() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []); // пустой массив — эффект только после первого рендера
return html`<input ref=${inputRef} />`;
}
Особенности:
useEffect с пустым массивом зависимостей выполняется
только после первого рендера.inputRef.current, так как
элемент уже смонтирован.Ref в Haunted можно использовать не только для стандартных HTML-элементов, но и для кастомных веб-компонентов. Это позволяет вызывать их методы или читать свойства напрямую.
function WrapperComponent() {
const childRef = useRef(null);
const callMethod = () => {
if (childRef.current) {
childRef.current.customMethod();
}
};
return html`
<my-child ref=${childRef}></my-child>
<button @click=${callMethod}>Вызвать метод дочернего компонента</button>
`;
}
Примечания:
childRef.current указывает на экземпляр
веб-компонента.useRef(null).ref=${myRef} — это нарушает реактивность.useEffect для безопасного
взаимодействия с DOM после рендера.Система ссылок на DOM-элементы в Haunted обеспечивает
контролируемый и реактивный доступ к элементам,
минимизирует необходимость ручного поиска через
querySelector, и полностью интегрирована с жизненным циклом
компонентов. Это делает работу с веб-компонентами более предсказуемой и
безопасной.