Intro.js — это легковесная библиотека для создания интерактивных пошаговых инструкций на веб-страницах. Одной из ключевых задач при интеграции интерактивных туров является корректная работа с динамическими элементами DOM. Часто на странице элементы создаются, удаляются или изменяются после загрузки, и для того чтобы тур оставался актуальным, необходимо отслеживать эти изменения.
Для динамических страниц Intro.js тесно интегрируется с нативным
механизмом JavaScript — MutationObserver. Этот объект
позволяет реагировать на изменения DOM, такие как добавление новых
узлов, удаление узлов или изменение атрибутов элементов.
Пример создания наблюдателя:
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('Добавлены или удалены элементы');
}
if (mutation.type === 'attributes') {
console.log(`Изменён атрибут ${mutation.attributeName}`);
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});
childList: true — отслеживание добавления и удаления
дочерних узлов.subtree: true — включает наблюдение за всеми вложенными
элементами.attributes: true — отслеживание изменений атрибутов
элементов.Это позволяет Intro.js корректно обновлять шаги, когда целевые элементы появляются динамически.
Когда элемент, на который ссылается шаг, появляется после
инициализации Intro.js, необходимо обновить шаги. Это делается методом
refresh():
introJs().start();
introJs().refresh();
Метод refresh() пересчитывает позиции всех элементов
тура, что особенно важно при динамических изменениях страницы.
Intro.js предоставляет несколько событий, которые можно использовать для синхронизации с DOM:
onbeforechange(targetElement) — вызывается перед
переходом к новому шагу. Можно использовать для проверки существования
элемента.onchange(targetElement) — вызывается при активации
нового шага, подходит для подгрузки данных или отображения скрытых
элементов.oncomplete() — срабатывает при завершении тура.Пример динамического добавления шага:
const intro = introJs();
intro.setOptions({
steps: [
{
element: '#step1',
intro: 'Первый шаг'
}
]
});
intro.onbeforechange(function(targetElement) {
if (!document.querySelector('#step2')) {
const newStep = document.createElement('div');
newStep.id = 'step2';
document.body.appendChild(newStep);
intro.addStep({
element: '#step2',
intro: 'Второй шаг добавлен динамически'
});
intro.refresh();
}
});
intro.start();
Этот подход гарантирует, что интерактивный тур не «сломается», если шаг появляется позже.
Даже если элемент существует, его содержимое может изменяться, что
влияет на подсказки и визуальное оформление. Использование
MutationObserver позволяет автоматически корректировать
Intro.js при изменении текста, классов или других атрибутов:
const targetNode = document.querySelector('#dynamicContent');
const contentObserver = new MutationObserver(() => {
introJs().refresh();
});
contentObserver.observe(targetNode, {
childList: true,
subtree: true,
characterData: true
});
characterData: true — отслеживание изменений текста
внутри узлов.refresh() обеспечивает правильное
позиционирование подсказок.Отслеживание всех изменений DOM может быть ресурсоёмким. Рекомендуется:
observer.observe),
вместо использования всего document.body.refresh():let refreshTimeout;
const debouncedRefresh = () => {
clearTimeout(refreshTimeout);
refreshTimeout = setTimeout(() => introJs().refresh(), 100);
};
observer = new MutationObserver(debouncedRefresh);
Для приложений на React, Vue или Angular шаги Intro.js часто должны синхронизироваться с состоянием компонентов. Основные принципы:
MutationObserver или lifecycle hooks
(например, componentDidUpdate в React) для обновления
шагов.refresh() каждый раз, когда DOM компоненты
изменяются.Отслеживание изменений в DOM позволяет Intro.js оставаться гибким и
корректно работать на динамических страницах. Основные инструменты —
MutationObserver, методы refresh() и
callback-функции событий Intro.js. Правильная комбинация этих механизмов
обеспечивает стабильный интерактивный тур вне зависимости от того, когда
и как появляются элементы на странице.