@coraltravelcenter/simple-react-dom-observer
v1.0.1
Published
Light version of observer for React (or any DOM) elements with appear
Readme
@coraltravelcenter/simple-react-dom-observer
Лёгкий обёрточный MutationObserver для отслеживания появления элементов в DOM по CSS-селектору.
Без зависимостей. RAF-батчинг. Типы для TypeScript генерируются автоматически.
Быстрый старт
import SimpleReactDomObserver from "@coraltravelcenter/react-dom-observer";
const obs = new SimpleReactDomObserver(".card", {
onAppear: (el) => {
// твой код: инициализация виджета, метрика, lazy-логика и т.д.
el.classList.add("seen");
},
debug: true, // опционально
observeExisting: true, // обработать уже существующие .card на старте
perElementOnce: true, // вызывать onAppear для каждого el один раз
});
obs.start();API
new SimpleReactDomObserver(selector, options?)
selector: string— CSS-селектор целевых элементов.options:onAppear?: (el: HTMLElement) => void— колбэк при появлении элемента в DOM.root?: Node = document.body— корневой узел, внутри которого отслеживаем изменения.observeExisting?: boolean = true— вызыватьonAppearдля уже находящихся в DOM элементов приstart().perElementOnce?: boolean = true— вызыватьonAppearдля каждого элемента только один раз за жизненный цикл наблюдателя.once?: boolean = false— глобальный режим «один раз»: после первогоonAppearавтоматически вызываетstop().debug?: boolean = false— консольные логи.
Методы
start(): void— запускает наблюдатель (идемпотентно).stop(): void— останавливает наблюдатель и снимает подписки (идемпотентно).check(): void— форс-скан DOM прямо сейчас (без ожидания следующего кадра).
Примеры
1) Инициализация виджета для динамического списка
const obs = new SimpleReactDomObserver("[data-widget]", {
onAppear(el) {
initWidget(el); // твоя функция
},
});
obs.start();2) Один раз глобально (например, найти первый баннер и выключиться)
new SimpleReactDomObserver(".promo-banner", {
once: true,
onAppear: (el) => bootPromo(el),
}).start();3) Повторные появления одного и того же элемента
Если элемент может удаляться и снова вставляться, и нужно каждый раз вызывать onAppear, отключи «once-per-element»:
const obs = new SimpleReactDomObserver(".toast", {
perElementOnce: false,
onAppear: showToastFromNode,
});
obs.start();4) Ограничение области наблюдения
Сузь root, чтобы снизить нагрузку и шум:
const container = document.querySelector("#app-root");
const obs = new SimpleReactDomObserver(".card", { root: container });
obs.start();Поведение и гарантии
- Батчинг через
requestAnimationFrame— множество DOM-мутаций схлопываются в один перескан на кадр. - Без утечек: учёт элементов через
WeakSetи аккуратные отписки вstop(). - Идемпотентность: повторные
start()/stop()безопасны. - Без зависимостей, дружит с tree-shaking (
"sideEffects": false).
Частые вопросы
Это про видимость в окне браузера?
Нет. Плагин реагирует на появление узла в DOM, а не на пересечение с вьюпортом. Для видимости — IntersectionObserver.
Нужно ли вызывать stop()?
Рекомендуется в жизненных циклах виджетов/страниц. В React — верни obs.stop() из useEffect.
Будет ли работать с Shadow DOM / web-компонентами?
Да, если указать root на нужный shadowRoot или контейнер, внутри которого происходят мутации.
Можно наблюдать несколько селекторов? Создай несколько инстансов, по одному на селектор. Это проще и прозрачнее.
Производительность
- Используй максимально узкий селектор и/или
root(вместо всегоdocument.body). - Держи
onAppearлёгким: выносите тяжёлую работу (загрузки, парсинг) за пределы кадра при необходимости. - Оставляй
perElementOnce: true, если повторные срабатывания не нужны.
Пример использования:
import SimpleReactDomObserver from "@coraltravelcenter/react-dom-observer";
const obs = new SimpleReactDomObserver(".item", {
onAppear(el) {
el.dataset.ready = "1";
},
});
obs.start();Ограничения
- Плагин не отслеживает исчезновение (
onDisappear) — это облегчённая версия.
Лицензия
MIT © Михаил / Coral Travel Center
