Библиотека Intro.js изначально ориентирована на работу в рамках одной страницы, однако в реальных приложениях часто требуется проводить пользователя через несколько экранов. Для этого необходимо управлять состоянием тура и корректно восстанавливать его после перехода.
Ключевая проблема — при смене страницы происходит перезагрузка DOM, и экземпляр Intro.js уничтожается. Поэтому требуется сохранять текущее состояние (шаг, прогресс, контекст) во внешнем хранилище.
Основной подход — фиксировать номер текущего шага перед переходом:
const intro = introJs();
intro.onbeforechange(function(targetElement) {
const step = this._currentStep;
localStorage.setItem('introStep', step);
});
Свойство _currentStep содержит индекс шага (начиная с
0). Его можно сохранять в:
localStorage — для простотыsessionStorage — если важно ограничить сессиюПосле загрузки следующей страницы необходимо восстановить сохранённый шаг:
const savedStep = parseInt(localStorage.getItem('introStep'), 10);
if (!isNaN(savedStep)) {
const intro = introJs();
intro.start().goToStep(savedStep + 1);
}
Важно учитывать, что метод goToStep принимает значение,
начиная с 1.
При многостраничном туре необходимо:
Пример настройки шагов:
introJs().setOptions({
steps: [
{
element: '#header',
intro: 'Заголовок страницы'
},
{
element: '#menu',
intro: 'Основное меню'
}
]
});
На следующей странице структура шагов должна быть согласована, либо логика должна учитывать различия.
Для перехода между страницами в рамках тура используется обработчик событий:
intro.onafterchange(function(targetElement) {
if (this._currentStep === 2) {
window.location.href = '/next-page.html';
}
});
Перед переходом важно:
На новой странице необходимо:
window.onl oad = function() {
const step = localStorage.getItem('introStep');
if (step !== null) {
introJs().start().goToStep(parseInt(step, 10) + 1);
}
};
После завершения тура необходимо удалить сохранённые данные:
intro.oncomplete(function() {
localStorage.removeItem('introStep');
});
intro.onexit(function() {
localStorage.removeItem('introStep');
});
Это предотвращает повторное автоматическое восстановление тура.
При переходе между страницами элементы могут:
В таких случаях необходимо задержать запуск:
setTimeout(function() {
introJs().start().goToStep(savedStep + 1);
}, 500);
Более надёжный вариант — отслеживание появления элемента:
function waitForElement(selector, callback) {
const interval = setInterval(() => {
if (document.querySelector(selector)) {
clearInterval(interval);
callback();
}
}, 100);
}
Альтернативный способ передачи состояния — через URL:
/next-page.html?step=2
Получение параметра:
const params = new URLSearchParams(window.location.search);
const step = parseInt(params.get('step'), 10);
Преимущества:
В одностраничных приложениях (React, Vue, Angular) переходы не перезагружают страницу, но DOM изменяется. В этом случае:
Пример:
router.afterEach(() => {
const step = localStorage.getItem('introStep');
if (step !== null) {
introJs().goToStep(parseInt(step, 10) + 1);
}
});
При несовпадении элементов возможны ошибки:
Решения:
intro: '...' без
elementsteps: [
document.querySelector('#menu') ? {
element: '#menu',
intro: 'Меню'
} : {
intro: 'Меню отсутствует на этой странице'
}
]
Для более сложных сценариев можно хранить:
Пример структуры:
const tourState = {
step: 2,
page: '/dashboard',
completed: false
};
localStorage.setItem('tourState', JSON.stringify(tourState));
Пользователь может прервать тур и вернуться позже. Для этого:
onexitintro.onexit(function() {
localStorage.setItem('introStep', this._currentStep);
});
Рекомендуется учитывать:
Проверка:
if (step >= 0 && step < steps.length) {
introJs().goToStep(step + 1);
} else {
localStorage.removeItem('introStep');
}
Для крупных проектов удобно выделить менеджер тура:
class TourManager {
static saveStep(step) {
localStorage.setItem('introStep', step);
}
static getStep() {
return parseInt(localStorage.getItem('introStep'), 10);
}
static clear() {
localStorage.removeItem('introStep');
}
}
Использование:
intro.onbeforechange(function() {
TourManager.saveStep(this._currentStep);
});
Грамотная обработка переходов превращает Intro.js из простой библиотеки подсказок в полноценный инструмент обучения пользователя внутри многостраничного интерфейса.