前端使用Driver.js快速實(shí)現(xiàn)新手指引全步驟及實(shí)現(xiàn)原理
前言
在當(dāng)今復(fù)雜的前端應(yīng)用生態(tài)中,一個(gè)清晰、友好的新手指引(Tour Guide)對(duì)于提升用戶體驗(yàn)和留存率至關(guān)重要。它能夠幫助用戶快速熟悉產(chǎn)品功能,降低學(xué)習(xí)成本。在眾多的指引庫(kù)中,Driver.js 以其輕量、靈活和無(wú)依賴的特性脫穎而出。
本文將帶你快速上手 Driver.js,并深入剖析其背后的實(shí)現(xiàn)原理,讓你不僅會(huì)使用,更能理解其工作機(jī)制。
一、什么是 Driver.js?
Driver.js 是一個(gè)輕量級(jí)(~4kB)、無(wú)外部依賴、高度可定制且強(qiáng)大的引導(dǎo)庫(kù)。它能夠通過(guò)高亮、彈窗解釋和聚焦的方式,將用戶的注意力吸引到頁(yè)面的特定元素上,從而完成產(chǎn)品引導(dǎo)、功能介紹或焦點(diǎn)聚焦等任務(wù)。
核心特點(diǎn):
- 零依賴:基于純 JavaScript 實(shí)現(xiàn),不依賴 jQuery、React 等。
- 輕量級(jí):極小的體積,對(duì)項(xiàng)目性能影響微乎其微。
- 高可定制性:可以自定義彈出框的樣式、文字、位置、動(dòng)畫等。
- 強(qiáng)大的 API:提供豐富的生命周期鉤子和方法,滿足各種復(fù)雜交互。
- 無(wú)障礙支持:對(duì)屏幕閱讀器友好,遵循可訪問(wèn)性最佳實(shí)踐。
二、快速上手:5分鐘實(shí)現(xiàn)新手指引
步驟 1:安裝
你可以通過(guò) npm/yarn 安裝,也可以直接通過(guò) CDN 引入。
方式一:NPM/Yarn
npm install driver.js # 或 yarn add driver.js
方式二:CDN (直接在 HTML 中引入)
<!-- 引入 CSS --> <link rel="stylesheet" rel="external nofollow" /> <!-- 引入 JS --> <script src="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.js.iife.js"></script>
步驟 2:初始化并啟動(dòng)引導(dǎo)
假設(shè)我們有一個(gè)react頁(yè)面,需要引導(dǎo)用戶使用
JavaScript 代碼:
import React, { useEffect, useRef } from 'react'
import { driver } from 'driver.js'
import "driver.js/dist/driver.css";
import './test.less'
const Driver = () => {
const driverRef = useRef(null);
// 添加全局函數(shù)供彈出框使用
window.handleGuideClick = () => {
driverRef.current.destroy();
};
const WELCOME_IMAGE = 'https://images.unsplash.com/photo-1533750349088-cd871a92f312?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80';
const guide = () => {
if (driverRef.current) {
driverRef.current.destroy();
}
driverRef.current = driver({
allowClose: false, // 是否有關(guān)閉按鈕
popoverClass: 'custom-driver-popover', // 添加自定義class
showProgress: false, // 首先確保配置中關(guān)閉進(jìn)度顯示
steps: [{
element: ".step1-pop",
popover: {
popoverClass:'step1',
title: "歡迎使用",
description: ` <div class="custom-popover-content">
<p>這是一個(gè)功能強(qiáng)大的應(yīng)用程序,將幫助您提高工作效率。</p>
<img src="${WELCOME_IMAGE}" alt="歡迎" />
<div class="button-container">
<button class="custom-button" onclick="handleGuideClick()">跳過(guò)</button>
</div>
</div>`,
showButtons: ["next"],
nextBtnText: "下一步",
onNext: () => {
console.log("正在從第一步移動(dòng)到第二步");
return true; // 返回false可阻止繼續(xù)
}
}
},
{
element: ".step2-pop",
popover: {
popoverClass:'step2',
description:'step2',
// showButtons: ["next", "previous"],
nextBtnText: "下一步",
prevBtnText: "上一步",
}
},
{
element: ".step3-pop",
popover: {
title: "完成",
description: "done",
nextBtnText: "關(guān)閉",
prevBtnText: "上一步"
}
}]
})
driverRef.current.drive()
}
useEffect(()=>{
guide()
},[])
return (
<div>
<div className='step1-pop'>步驟一</div>
<div className='step2-pop'>步驟二</div>
<div className='step3-pop'>步驟三</div>
</div>
)
}
export default Driver
less 代碼:
.custom-driver-popover {
// text-align: left;
background-color: #fff;
height: auto;
}
.custom-popover-content img {
width: 100%;
border-radius: 5px;
margin: 10px 0;
}
.custom-button {
background-color: #3b82f6;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
margin-top: 10px;
cursor: pointer;
}
.step1-pop,.step2-pop,.step3-pop{
position: fixed;
width: 100px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: #fff;
font-weight: 600;
}
.step1-pop{
left: 100px;
top: 100px;
background-color: pink;
}
.step2-pop{
left: 100px;
bottom: 100px;
background-color: palegreen;
}
.step3-pop{
right: 100px;
bottom: 100px;
background-color: orange;
}
只需以上幾步,一個(gè)基礎(chǔ)但完整的新手指引功能就實(shí)現(xiàn)了!
效果:

進(jìn)階配置:生命周期鉤子
Driver.js 提供了強(qiáng)大的生命周期鉤子,讓你在引導(dǎo)的各個(gè)階段執(zhí)行自定義邏輯。
onHighlightStarted: (element) => {
console.log('開(kāi)始高亮元素:', element);
// 例如,可以在高亮前先滾動(dòng)到該元素
element.scrollIntoView({ behavior: 'smooth' });
},
onHighlighted: (element) => {
console.log('元素高亮完成:', element);
},
onDeselected: (element) => {
console.log('元素取消高亮:', element);
},
onReset: (element) => {
console.log('引導(dǎo)被關(guān)閉或完成');
}
三、實(shí)現(xiàn)原理剖析
理解了如何使用,我們?cè)偕钊胍粚樱纯?Driver.js 是如何在幕后工作的。其核心原理可以概括為以下幾點(diǎn):
1. 元素高亮與聚焦
這是 Driver.js 最核心的視覺(jué)效果。它通過(guò)動(dòng)態(tài)計(jì)算目標(biāo)元素的位置和尺寸來(lái)實(shí)現(xiàn)。
- 計(jì)算位置:使用
Element.getBoundingClientRect()API 獲取目標(biāo)元素相對(duì)于視口(viewport)的精確位置(top, left, width, height)。 - 創(chuàng)建高亮層:在頁(yè)面中動(dòng)態(tài)插入一個(gè)
div作為高亮層。這個(gè)層的尺寸和位置被設(shè)置為與目標(biāo)元素完全一致(加上配置的padding)。 - CSS 樣式:為該高亮層應(yīng)用特定的樣式,通常是
border(如發(fā)光效果)和box-shadow,并設(shè)置z-index為一個(gè)極高的值(如 10000),確保它浮在所有常規(guī)內(nèi)容之上。 - 遮罩背景:在整個(gè)頁(yè)面上創(chuàng)建一個(gè)巨大的遮罩層(Overlay),覆蓋整個(gè)視口。這個(gè)遮罩層通常有一個(gè)半透明的背景色(由
opacity配置),并設(shè)置pointer-events: auto來(lái)攔截頁(yè)面上的點(diǎn)擊。然后,在高亮層對(duì)應(yīng)的區(qū)域使用clip-path或CSS Mask等技術(shù)“挖”一個(gè)洞,或者更簡(jiǎn)單的,在高亮層區(qū)域設(shè)置pointer-events: none來(lái)讓點(diǎn)擊“穿透”到目標(biāo)元素。Driver.js 采用的是后一種 pointer-events 方案,它創(chuàng)建了一個(gè)全屏遮罩,但將高亮層區(qū)域的pointer-events設(shè)為none。
2. 彈窗定位
解釋性彈窗(Popover)的位置是動(dòng)態(tài)計(jì)算的。
- 可用空間檢查:根據(jù)配置的
position(如'top'),Driver.js 會(huì)檢查那個(gè)方向是否有足夠的空間來(lái)顯示彈窗(不會(huì)超出屏幕邊界)。 - 動(dòng)態(tài)定位:如果首選方向空間不足,它會(huì)自動(dòng)尋找最佳位置(例如,如果
top不夠,就嘗試bottom)。 - CSS 絕對(duì)定位:彈窗使用
position: fixed定位,并通過(guò) JavaScript 動(dòng)態(tài)計(jì)算并設(shè)置其top和left值,使其精確地出現(xiàn)在高亮元素的旁邊。
四、總結(jié)
Driver.js 通過(guò)巧妙的 動(dòng)態(tài) DOM 操作、精確的幾何計(jì)算 和 簡(jiǎn)單的狀態(tài)管理,為我們提供了一個(gè)強(qiáng)大而易用的新手指引解決方案。
它的優(yōu)勢(shì)在于:
- 開(kāi)箱即用:簡(jiǎn)單配置即可實(shí)現(xiàn)大部分常見(jiàn)需求。
- 侵入性低:不需要修改你現(xiàn)有的業(yè)務(wù)組件代碼。
- 原理清晰:理解了其原理后,可以更好地應(yīng)對(duì)各種邊界情況和自定義需求。
附:Driver.js導(dǎo)入報(bào)錯(cuò)解決方案
使用driver.js進(jìn)行系統(tǒng)流程引導(dǎo)時(shí),發(fā)現(xiàn)怎么導(dǎo)入都報(bào)錯(cuò),官方代碼是這樣的
import { driver } from "driver.js";
import "driver.js/dist/driver.css";
const driverObj = driver();
driverObj.highlight({
element: "#some-element",
popover: {
title: "Title",
description: "Description"
}
});這里我使用的是driver.js@1.3.6,代碼如下
import { Driver } from 'driver.js';
import 'driver.js/dist/driver.css';
const driver = new Driver({
animate: true,
overlayColor: 'rgba(0, 0, 0, 0.7)',
opacity: 0.7,
padding: 10,
allowClose: true,
doneBtnText: '完成',
nextBtnText: '下一步',
prevBtnText: '上一步',
stageBackground: '#fff',
primaryColor: '#409EFF',
});
export const startTour = (steps: any) => {
driver.defineSteps(steps);
driver.start();
};
export default driver;報(bào)錯(cuò)Driver only refers to a type, but is being used as a value here
查看driver.js發(fā)現(xiàn)Drivers只是一個(gè)接口類型,而實(shí)際創(chuàng)建實(shí)例的是driver()工廠函數(shù),創(chuàng)建實(shí)例的方式是通過(guò)driver(options)函數(shù)創(chuàng)建實(shí)例而非new Driver()(這個(gè)只是接口,不能實(shí)例化)
另外還需要導(dǎo)入類型定義,用于TypeScript類型提示
更正后代碼如下
tour.ts
import { driver } from 'driver.js';
import 'driver.js/dist/driver.css';
// 導(dǎo)入類型定義(可選,用于 TypeScript 類型提示)
import type { Config, DriveStep } from 'driver.js';
// 通過(guò) driver() 函數(shù)創(chuàng)建實(shí)例(傳入配置項(xiàng))
const driverInstance = driver({
animate: true,
overlayColor: 'rgba(0, 0, 0, 0.7)',
opacity: 0.7,
padding: 10,
allowClose: true,
doneBtnText: '完成',
nextBtnText: '下一步',
prevBtnText: '上一步',
stageBackground: '#fff',
primaryColor: '#409EFF',
} as Config); // 類型斷言確保配置符合 Config 類型
// 定義步驟類型(直接使用 driver.js 的 DriveStep 接口)
export const startTour = (steps: DriveStep[]) => {
driverInstance.setSteps(steps);
driverInstance.drive();
};
export default driverInstance;
這時(shí)候就能夠在其他組件中使用了
<script setup lang="ts">
import { startTour } from '../tour.ts';
const startGuide = () => {
startTour([
{
element: '.aside-class',
popover: {
title: '',
description: ''
}
},{
element: '.aside-class-1',
popover: {
title: '',
description: ''
}
},
])
};
</script>
<template>
<el-button id="re_main" @click="startGuide">功能引導(dǎo)</el-button>
</template>
<style scoped>
</style>driver.js是能夠跨組件引導(dǎo)的,只要元素已掛載到DOM中,并且通過(guò)element參數(shù)傳入css選擇器或者直接傳入DOM元素對(duì)象,driver.js都能夠識(shí)別并引導(dǎo),當(dāng)然跨組件引導(dǎo)的核心是確保目標(biāo)元素的選擇器唯一且在引導(dǎo)執(zhí)行時(shí)已存在于 DOM 中
到此這篇關(guān)于前端使用Driver.js快速實(shí)現(xiàn)新手指引全步驟及實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)前端Driver.js實(shí)現(xiàn)新手指引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript獲得url所有參數(shù)鍵值表的方法
這篇文章主要介紹了JavaScript獲得url所有參數(shù)鍵值表的方法,實(shí)例分析了javascript操作URL的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
原生js實(shí)現(xiàn)表格循環(huán)滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)表格循環(huán)滾動(dòng),每次滾動(dòng)一行停頓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
微信小程序自定義toast彈窗效果的實(shí)現(xiàn)代碼
微信小程序里面的自帶彈窗icon只有兩種,success和loading。這篇文章主要介紹了微信小程序之自定義toast彈窗效果的實(shí)現(xiàn)代碼 ,需要的朋友可以參考下2018-11-11
JS組件Bootstrap Table表格多行拖拽效果實(shí)現(xiàn)代碼
這篇文章主要介紹了JS組件Bootstrap Table表格多行拖拽效果實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-12-12
基于JavaScript中字符串的match與replace方法(詳解)
下面小編就為大家介紹一下JavaScript中的字符串的match與replace方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
xmlplus組件設(shè)計(jì)系列之文本框(TextBox)(3)
xmlplus 是一個(gè)JavaScript框架,用于快速開(kāi)發(fā)前后端項(xiàng)目。這篇文章主要介紹了xmlplus組件設(shè)計(jì)系列之文本框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
41個(gè)Web開(kāi)發(fā)者必須收藏的JavaScript實(shí)用技巧
41個(gè)Web開(kāi)發(fā)者必須收藏的JavaScript實(shí)用技巧,分享給大家,感興趣的小伙伴們可以參考一下2016-07-07

