引导效果 driver.js 封装使用
shell
pnpm add driver.js查看封装代码
ts
import { driver as createDriver, type Config, type DriveStep } from 'driver.js'
import 'driver.js/dist/driver.css'
import { onUnmounted } from 'vue'
// 配置文档看 https://driverjs.com/docs/configuration
// driver 是单例模式
export function useStepDriver(option: Config) {
const driver = createDriver()
const showDriver = () => {
driver.setConfig({
nextBtnText: '下一步',
prevBtnText: '上一步',
doneBtnText: '完成',
allowClose: false, // 空白处不让关闭
smoothScroll: false,
...option
})
driver.drive()
}
onUnmounted(() => {
driver.destroy()
})
return { showDriver, driver }
}
export function useSingleDriver(step: DriveStep) {
const driver = createDriver()
const showDriver = () => {
driver.setConfig({ allowClose: true })
driver.highlight({
...step
})
}
onUnmounted(() => {
driver.destroy()
})
return { showDriver, driver }
}基础用法
简单示例 只显示一个
步骤示例 显示几个步骤
欲买桂花同载酒,终不似,少年游。
晓看天色暮看云,行也思君,坐也思君。
异步渲染示例
欲买桂花同载酒,终不似,少年游。
查看代码
vue
<template>
<div class="base-demo">
<a-divider> 简单示例 只显示一个 </a-divider>
<a-button type="primary" @click="showBaseDriver">show</a-button>
</div>
<div class="step-demo">
<a-divider> 步骤示例 显示几个步骤 </a-divider>
<div class="step-demo-container">
<div class="p">欲买桂花同载酒,终不似,少年游。</div>
<div class="p">晓看天色暮看云,行也思君,坐也思君。</div>
</div>
<a-button type="primary" @click="showStepDriver">show</a-button>
</div>
<div class="async-demo">
<a-divider> 异步渲染示例 </a-divider>
<div class="async-demo-container">
<div class="p">欲买桂花同载酒,终不似,少年游。</div>
<div class="p" v-if="asyncShow">晓看天色暮看云,行也思君,坐也思君。</div>
</div>
<a-button type="primary" @click="showAsyncDriver">show</a-button>
</div>
</template>
<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import { useSingleDriver, useStepDriver } from './driver'
const { showDriver: showBaseDriver } = useSingleDriver({
element: '.base-demo',
popover: {
title: '简单示例的标题',
description: '我来实现一个简单示例的引导程序'
}
})
const { showDriver: showStepDriver } = useStepDriver({
steps: [
{ element: '.step-demo', popover: { title: '步骤1', description: '整个大块' } },
{ element: '.step-demo-container', popover: { title: '步骤2', description: '内部div' } },
{
element: '.step-demo-container > .p:nth-child(1)',
popover: { title: '步骤3', description: '第一段' }
},
{
element: '.step-demo-container > .p:nth-child(2)',
popover: { title: '步骤4', description: '第二段' }
}
]
})
const asyncShow = ref(false)
const { showDriver: showAsyncDriver, driver: asyncDriver } = useStepDriver({
steps: [
{ element: '.async-demo', popover: { title: '步骤1', description: '内部div' } },
{
element: '.async-demo-container > .p:nth-child(1)',
popover: {
title: '步骤2',
description: '第一段',
onNextClick() {
asyncShow.value = true
nextTick(() => asyncDriver.moveNext())
}
}
},
{
element: '.async-demo-container > .p:nth-child(2)',
popover: { title: '步骤3', description: '某种情况下的第二段' },
onDeselected() {
asyncShow.value = false
}
}
]
})
</script>
<style scoped>
.step-demo-container > .p,
.async-demo-container > .p {
margin-bottom: 16px;
}
</style>自定义
自定义示例
第一步
第二步
第三步
查看代码
vue
<template>
<div class="custom-demo">
<a-divider> 自定义示例 </a-divider>
<div class="step-container">
<Steps :current="state.current" :items="state.steps" />
<div style="margin: 16px 0">
<p class="step-content-1" v-if="state.current === 1">第一步的内容</p>
<p class="step-content-2" v-if="state.current === 2">第二步的内容</p>
<p class="step-content-3" v-if="state.current === 3">第三步的内容</p>
</div>
</div>
<a-button type="primary" @click="openDriver">show</a-button>
</div>
</template>
<script setup lang="ts">
import { Steps } from 'ant-design-vue'
import type { Config } from 'driver.js'
import { nextTick, reactive } from 'vue'
import { useStepDriver } from './driver'
const state = reactive({
current: 0,
steps: [{ title: '第一步' }, { title: '第二步' }, { title: '第三步' }]
})
const driverOption = reactive({
steps: [
{
element: '.step-container',
popover: { title: '步骤1', description: '第一步是为了xxx' }
},
{
element: '.step-container',
popover: { title: '步骤2', description: '第二步是为了xxx' }
},
{
element: '.step-container',
popover: { title: '步骤3', description: '第三步是为了xxx' }
}
],
onNextClick() {
if (driver.isLastStep()) {
state.current = 0
driver.destroy()
return
}
state.current++
console.log(' onNextClick state.current ', state.current)
nextTick(() => driver.moveNext())
},
onPrevClick() {
state.current--
console.log(' onPrevClick state.current ', state.current)
nextTick(() => driver.movePrevious())
},
onCloseClick() {
state.current = 0
driver.destroy()
}
}) as Config
const { showDriver, driver } = useStepDriver(driverOption)
function openDriver() {
state.current = 1
nextTick(() => showDriver())
}
</script>
<style scoped>
.custom-demo {
.a-button {
margin-top: 16px;
}
}
</style>