Управление состоянием в библиотеке Driver.js играет ключевую роль при построении сложных пользовательских сценариев: интерактивных туров, обучающих подсказок и пошаговых инструкций. Под состоянием понимается совокупность текущих параметров, описывающих положение тура: активный шаг, статус (запущен или завершён), конфигурация элементов и поведение интерфейса.
Driver.js не использует централизованное хранилище состояния (как Redux или Vuex), однако предоставляет механизмы для отслеживания и управления состоянием через API экземпляра.
Создание экземпляра:
import Driver from "driver.js";
const driver = new Driver();
Экземпляр driver фактически инкапсулирует текущее
состояние:
Driver.js позволяет получать информацию о текущем шаге:
const activeElement = driver.getActiveElement();
const activeStep = driver.getActiveStep();
Ключевые особенности:
getActiveElement() возвращает DOM-элемент текущего
шагаgetActiveStep() возвращает объект конфигурации
шагаПример структуры шага:
{
element: "#button",
popover: {
title: "Кнопка",
description: "Описание кнопки"
}
}
Это позволяет:
Driver.js предоставляет методы для контроля состояния тура:
driver.start();
driver.moveNext();
driver.movePrevious();
driver.reset();
driver.hasNextStep();
driver.hasPreviousStep();
Состояния:
| Состояние | Описание |
|---|---|
| Не запущен | До вызова start() |
| Активен | Во время прохождения шагов |
| Завершён | После последнего шага или reset |
Проверка активности:
driver.isActivated();
Возвращает true, если тур активен.
Проверка наличия следующего шага:
if (driver.hasNextStep()) {
driver.moveNext();
}
Это важно для предотвращения ошибок при навигации.
В сложных приложениях состояние Driver.js часто синхронизируется с внешним состоянием (например, React/Vue):
driver.defineSteps(steps);
driver.start();
setCurrentStep(driver.getActiveStep());
Обновление состояния при переходах:
driver.on("next", () => {
updateUI(driver.getActiveStep());
});
Driver.js предоставляет хуки, позволяющие отслеживать изменения:
const driver = new Driver({
onHighlightStarted: (element) => {
console.log("Шаг начался", element);
},
onHighlighted: (element) => {
console.log("Шаг отображён");
},
onDeselected: (element) => {
console.log("Шаг завершён");
},
onReset: () => {
console.log("Тур сброшен");
}
});
Назначение событий:
Driver.js не сохраняет состояние автоматически. Для этого используется внешнее хранилище:
driver.on("next", () => {
localStorage.setItem("tour-step", driver.getActiveStepIndex());
});
Восстановление состояния:
const savedStep = localStorage.getItem("tour-step");
if (savedStep !== null) {
driver.start(savedStep);
}
Driver.js использует индекс шагов для определения текущего состояния:
driver.getActiveStepIndex();
Можно запускать тур с конкретного шага:
driver.start(2);
Это полезно для:
Driver.js позволяет изменять шаги во время выполнения:
driver.defineSteps([
{
element: "#new-element",
popover: {
title: "Новый шаг"
}
}
]);
Важно учитывать:
start()Часто требуется пропуск шагов:
if (user.isAdmin) {
driver.moveNext();
} else {
driver.moveNext();
driver.moveNext();
}
Более гибкий подход — формирование шагов заранее:
const steps = [];
if (user.isAdmin) {
steps.push(adminStep);
}
driver.defineSteps(steps);
Driver.js влияет на DOM:
Контроль через параметры:
const driver = new Driver({
allowClose: false,
overlayOpacity: 0.7,
stagePadding: 5
});
Состояние интерфейса напрямую связано с состоянием тура.
Полный сброс:
driver.reset();
Это:
После reset требуется новый start().
1. Попытка перехода без проверки:
driver.moveNext(); // ошибка, если шагов больше нет
Решение:
if (driver.hasNextStep()) {
driver.moveNext();
}
2. Потеря состояния при перерисовке UI
В SPA-приложениях DOM может пересоздаваться:
Решение:
3. Несинхронизированные шаги
Если элементы появляются динамически:
setTimeout(() => {
driver.start();
}, 500);
Лучше использовать события рендера.
1. Централизованное управление
Создание сервиса:
class TourManager {
constructor() {
this.driver = new Driver();
}
startTour(steps) {
this.driver.defineSteps(steps);
this.driver.start();
}
}
2. Интеграция с состоянием приложения
React пример:
useEffect(() => {
if (isTourActive) {
driver.start();
} else {
driver.reset();
}
}, [isTourActive]);
3. Декларативное описание шагов
Хранение конфигурации отдельно:
const tourSteps = [
{ element: "#a", popover: { title: "A" } },
{ element: "#b", popover: { title: "B" } }
];
Комбинирование состояния и логики:
driver.on("next", () => {
const stepIndex = driver.getActiveStepIndex();
if (stepIndex === 2) {
openModal();
}
});
Если элемент появляется позже:
async function waitForElement(selector) {
while (!document.querySelector(selector)) {
await new Promise(r => setTimeout(r, 100));
}
}
await waitForElement("#dynamic");
driver.start();
Отслеживание окончания:
driver.on("reset", () => {
console.log("Тур завершён");
});
Или вручную:
if (!driver.hasNextStep()) {
driver.reset();
}
Для разных сценариев:
const onboardingDri ver = new Driver();
const featureDriver = new Driver();
Каждый экземпляр имеет своё состояние.
Прерывание тура:
document.querySelector("#cancel").addEventListener("click", () => {
driver.reset();
});
Переход по действию:
button.addEventListener("click", () => {
driver.moveNext();
});
Driver.js позволяет управлять не только шагами, но и поведением:
const driver = new Driver({
animate: true,
opacity: 0.75,
padding: 10
});
Эти параметры влияют на визуальное состояние интерфейса.
Полезно логировать:
console.log({
activeStep: driver.getActiveStep(),
index: driver.getActiveStepIndex(),
active: driver.isActivated()
});
Это помогает при разработке сложных туров.
Управление состоянием в Driver.js строится вокруг экземпляра драйвера, его методов и событий. Грамотное использование этих инструментов позволяет создавать устойчивые, предсказуемые и гибкие пользовательские сценарии даже в динамических интерфейсах.