Hooks 与事件
Driver.js 提供生命周期 hooks,让你在导览开始、步骤切换、弹层渲染、关闭销毁等时机执行业务逻辑。
Hooks 适合处理四类事情:
- 记录用户是否看过引导。
- 上报步骤浏览和完成埋点。
- 在进入下一步前保存表单或打开面板。
- 在路由切换、权限变化时清理导览。
常见 hooks
const driverObj = driver({
onHighlightStarted: (element, step) => {
console.log("开始高亮", element, step);
},
onHighlighted: (element, step) => {
console.log("高亮完成", element, step);
},
onDeselected: (element, step) => {
console.log("离开当前步骤", element, step);
},
onDestroyed: () => {
console.log("导览已结束或被关闭");
},
steps: [
{
element: "#create-project",
popover: {
title: "创建项目",
description: "从这里开始创建项目。",
},
},
],
});
不同 hooks 的参数会随触发时机不同而变化。实际编码时建议参考编辑器类型提示和官方 API 文档。
上报导览完成
const TOUR_KEY = "dashboard-tour-shown";
const driverObj = driver({
onDestroyed: () => {
localStorage.setItem(TOUR_KEY, "1");
analytics.track("dashboard_tour_closed");
},
steps: tourSteps,
});
如果要区分“看完”和“中途关闭”,可以结合当前步骤索引判断。
const driverObj = driver({
onDestroyed: () => {
const state = driverObj.getState();
const completed = state.activeIndex === tourSteps.length - 1;
analytics.track("dashboard_tour_end", {
completed,
activeIndex: state.activeIndex,
});
},
steps: tourSteps,
});
自定义下一步行为
有时下一步之前要先展开菜单、切换标签页或保存状态。可以在按钮 hook 中接管默认行为:
const driverObj = driver({
steps: [
{
element: "#settings-button",
popover: {
title: "打开设置",
description: "先打开设置面板,再查看下一步。",
onNextClick: async () => {
await openSettingsPanel();
driverObj.moveNext();
},
},
},
{
element: "#settings-panel",
popover: {
title: "设置面板",
description: "这里可以调整团队偏好。",
},
},
],
});
如果接管了按钮行为,需要自己调用 moveNext() 或 movePrevious(),否则引导不会继续。
按步骤设置 hooks
除了全局 hooks,也可以在某个 step 上设置局部逻辑:
const driverObj = driver({
steps: [
{
element: "#advanced-menu",
onHighlightStarted: () => {
document.querySelector("#sidebar").classList.add("expanded");
},
popover: {
title: "高级菜单",
description: "展开后可以看到更多配置项。",
},
},
],
});
局部 hooks 适合处理某一步特有的 DOM 状态。
清理副作用
如果 hook 中修改了页面状态,记得在导览结束时恢复:
const sidebar = document.querySelector("#sidebar");
const driverObj = driver({
onDestroyed: () => {
sidebar?.classList.remove("expanded");
},
steps: [
{
element: "#advanced-menu",
onHighlightStarted: () => {
sidebar?.classList.add("expanded");
},
popover: {
title: "高级菜单",
description: "这里包含更多配置项。",
},
},
],
});
Hooks 很强,但不要把复杂业务流程都塞进导览。导览应该说明界面,而不是替代界面本身。