React 与 Vue 集成
Driver.js 不依赖框架。集成到 React 或 Vue 时,重点不是 API 本身,而是处理好组件生命周期、DOM 渲染时机和清理逻辑。
React 示例
React 中通常在 useEffect 里创建实例,并在组件卸载时销毁。
import { useEffect, useRef } from "react";
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
export function DashboardHelp() {
const createButtonRef = useRef(null);
useEffect(() => {
const driverObj = driver({
showProgress: true,
steps: [
{
element: createButtonRef.current,
popover: {
title: "创建项目",
description: "点击这里创建你的第一个项目。",
},
},
{
element: "#project-list",
popover: {
title: "项目列表",
description: "所有项目都会显示在这里。",
},
},
],
});
return () => {
driverObj.destroy();
};
}, []);
return <button ref={createButtonRef}>创建项目</button>;
}
如果实例只在点击帮助按钮时使用,也可以把创建逻辑放到事件处理函数中。
React 点击启动
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
const steps = [
{
element: "#create-project",
popover: {
title: "创建项目",
description: "从这里开始创建项目。",
},
},
];
export function HelpButton() {
function startTour() {
const driverObj = driver({ steps });
driverObj.drive();
}
return <button onClick={startTour}>页面引导</button>;
}
这种写法简单,但如果导览过程中路由切换,仍然需要在路由层处理清理。
Vue 示例
Vue 3 中可以在 onMounted 后访问 DOM,在 onBeforeUnmount 中销毁实例。
<script setup>
import { onBeforeUnmount, onMounted, ref } from "vue";
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
const createButton = ref(null);
let driverObj;
onMounted(() => {
driverObj = driver({
showProgress: true,
steps: [
{
element: createButton.value,
popover: {
title: "创建项目",
description: "点击这里创建你的第一个项目。",
},
},
{
element: "#project-list",
popover: {
title: "项目列表",
description: "这里展示你的项目。",
},
},
],
});
});
onBeforeUnmount(() => {
driverObj?.destroy();
});
function startTour() {
driverObj?.drive();
}
</script>
<template>
<button ref="createButton">创建项目</button>
<button @click="startTour">页面引导</button>
</template>
路由切换清理
单页应用中,导览可能跨页面或被路由打断。建议在路由切换前销毁当前实例:
router.beforeEach(() => {
activeDriver?.destroy();
activeDriver = null;
});
如果导览确实需要跨页面,最好拆成多个页面内导览,而不是让一个 tour 依赖多次路由跳转。
封装建议
中大型项目可以封装一个 startTour(name) 方法:
const tours = {
dashboard: [
{
element: "#create-project",
popover: {
title: "创建项目",
description: "从这里创建项目。",
},
},
],
};
let activeDriver;
export function startTour(name) {
activeDriver?.destroy();
activeDriver = driver({
showProgress: true,
steps: tours[name] || [],
});
activeDriver.drive();
}
这样可以统一处理中文按钮、埋点、已读状态和销毁逻辑。