Tour 导览
新粗野主义风格的分步引导组件。使用 Canvas 局部挖孔遮罩高亮目标元素,配合弹出面板展示步骤说明,支持四方向定位、键盘导航和视口边界约束,帮助用户快速了解界面功能。
预览
安装
pnpm dlx brutx-vue@latest add tour用法
基础用法
定义步骤数组,通过 v-model:open 和 v-model:current 控制导览的显示状态和当前步骤:
<script setup>
import { ref } from 'vue'
import { Tour } from 'brutx-ui-vue'
const isOpen = ref(true)
const current = ref(0)
const steps = [
{
target: '#step-nav',
title: '导航栏',
description: '这里是主导航区域,包含应用的主要入口链接。',
placement: 'bottom',
},
{
target: '#step-search',
title: '搜索功能',
description: '使用搜索框快速查找你需要的内容。',
placement: 'right',
},
{
target: '#step-profile',
title: '个人中心',
description: '点击头像可以进入个人中心管理你的资料。',
placement: 'left',
},
]
</script>
<template>
<Tour v-model:open="isOpen" v-model:current="current" :steps="steps" />
</template>自定义 placement 和 mask
每个步骤可以独立设置弹出方向(placement)和是否显示遮罩(mask)。当步骤未指定时,继承组件级别的 mask 属性(默认 true)。
<script setup>
import { ref } from 'vue'
import { Tour } from 'brutx-ui-vue'
const isOpen = ref(true)
const current = ref(0)
const steps = [
{
target: '#hero-section',
title: '欢迎',
description: '这是首屏展示区域。',
placement: 'top',
mask: true,
},
{
target: '#sidebar',
title: '侧边栏',
description: '侧边栏不显示遮罩。',
placement: 'right',
mask: false,
},
]
</script>
<template>
<Tour v-model:open="isOpen" v-model:current="current" :steps="steps" />
</template>监听事件
通过 @skip、@finish 和 @close 事件响应用户操作:
<script setup>
import { ref } from 'vue'
import { Tour } from 'brutx-ui-vue'
const isOpen = ref(true)
const current = ref(0)
const steps = [
{ target: '#feature-a', title: '功能 A', description: '了解功能 A 的用途。' },
{ target: '#feature-b', title: '功能 B', description: '了解功能 B 的用途。' },
]
const onSkip = () => {
console.log('用户跳过了导览')
}
const onFinish = () => {
console.log('用户完成了所有步骤')
}
const onClose = () => {
console.log('导览已关闭')
}
</script>
<template>
<Tour
v-model:open="isOpen"
v-model:current="current"
:steps="steps"
@skip="onSkip"
@finish="onFinish"
@close="onClose"
/>
</template>自定义滚动行为
通过 scrollIntoViewOptions 自定义目标元素滚动到视口时的行为:
<script setup>
import { ref } from 'vue'
import { Tour } from 'brutx-ui-vue'
const isOpen = ref(true)
const current = ref(0)
const steps = [
{ target: '#section-1', title: '第一部分', description: '页面顶部的内容。' },
{ target: '#section-2', title: '第二部分', description: '需要向下滚动才能看到。' },
]
</script>
<template>
<Tour
v-model:open="isOpen"
v-model:current="current"
:steps="steps"
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
/>
</template>数据类型
TourStep
interface TourStep {
target: string | HTMLElement
title?: string
description?: string
placement?: 'top' | 'bottom' | 'left' | 'right'
mask?: boolean
}| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target | string | HTMLElement | — | 目标元素,CSS 选择器字符串或 DOM 元素引用(必需) |
title | string | — | 步骤标题 |
description | string | — | 步骤描述文本 |
placement | 'top' | 'bottom' | 'left' | 'right' | 'bottom' | 弹出面板相对目标元素的显示方向 |
mask | boolean | — | 是否为此步骤显示遮罩,未指定时继承组件级 mask 属性 |
导出类型
import type { TourStep, TourProps } from 'brutx-ui-vue'API 参考
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
steps必填 | TourStep[] | — | 按顺序提供导览步骤;每一步通过 CSS 选择器或 HTMLElement 指定目标,并可带标题、说明、显示方向及遮罩设置。 |
详情声明类型TourStep[] 关联类型 TourStep 类型定义 — TourStepexport interface TourStep {
target: string | HTMLElement
title?: string
description?: string
placement?: 'top' | 'bottom' | 'left' | 'right'
mask?: boolean
}默认值详情
来源packages/ui/src/components/tour/types.ts | |||
mask | boolean | undefined | true | 设置步骤目标之外是否显示遮罩;默认显示,可由当前 TourStep.mask 单独覆盖。 |
详情声明类型boolean | undefined 字面量
默认值详情
来源packages/ui/src/components/tour/types.ts | |||
scrollIntoViewOptions | ScrollIntoViewOptions | undefined | undefined | 设置切换步骤前滚动目标元素时传给 scrollIntoView 的选项;未指定时使用 block: center、inline: nearest。 |
详情声明类型ScrollIntoViewOptions | undefined 默认值详情
来源packages/ui/src/components/tour/types.ts | |||
current | number | undefined | 0 | 当前导览步骤的从 0 开始索引,可通过 v-model:current 受控同步,默认从第一步开始。 |
详情声明类型number | undefined 默认值详情
来源packages/ui/src/components/tour/Tour.vue | |||
open | boolean | undefined | true | 控制导览是否打开,可通过 v-model:open 受控同步;默认打开。 |
详情声明类型boolean | undefined 字面量
默认值详情
来源packages/ui/src/components/tour/Tour.vue | |||
| 名称 | 签名或类型 | 说明 |
|---|---|---|
@close | [] | 用户跳过或完成导览并关闭时发出。 |
详情声明类型[] 来源packages/ui/src/components/tour/Tour.vue | ||
@update:open | [value: boolean] | 导览打开状态变化时发出新布尔值,用于同步 v-model:open。 |
详情声明类型[value: boolean] 字面量
来源packages/ui/src/components/tour/Tour.vue | ||
@finish | [] | 用户在最后一步选择结束时发出。 |
详情声明类型[] 来源packages/ui/src/components/tour/Tour.vue | ||
@update:current | [value: number] | 当前步骤变化时发出新索引,用于同步 v-model:current。 |
详情声明类型[value: number] 来源packages/ui/src/components/tour/Tour.vue | ||
@skip | [] | 用户选择跳过导览时发出。 |
详情声明类型[] 来源packages/ui/src/components/tour/Tour.vue | ||
可访问性
- 键盘操作:按
Escape键跳过导览,按Enter键进入下一步或完成导览 - ARIA 属性:弹出面板中的步骤标题和描述文本通过语义化标签呈现,按钮包含可访问的文本标签
- 焦点管理:导览打开期间面板内的按钮可聚焦,关闭后自动释放
- 视口约束:弹出面板自动约束在视口安全区域内,不会超出屏幕边缘
常见问题
Q: 目标元素不在可视区域内怎么办?
A: Tour 在切换步骤时会自动调用 scrollIntoView 将目标元素滚动到视口中心位置。可以通过 scrollIntoViewOptions 属性自定义滚动行为,例如设置 { behavior: 'smooth', block: 'start' } 实现平滑滚动到顶部。
Q: 目标元素大小发生变化后遮罩位置不对?
A: Tour 内部使用 ResizeObserver 监听目标元素的尺寸变化,自动重新计算遮罩挖孔区域和弹出面板位置。同时注册了全局 scroll 和 resize 事件监听器,防止页面滚动或窗口缩放导致定位漂移。所有监听器在组件卸载时自动注销。
Q: 如何使用 DOM 元素引用代替 CSS 选择器?
A: target 属性支持直接传入 HTMLElement 实例。在 Vue 中可以通过模板引用(ref)获取元素后传给 target:
<script setup>
import { ref } from 'vue'
import { Tour } from 'brutx-ui-vue'
const targetEl = ref(null)
const isOpen = ref(true)
const current = ref(0)
const steps = [{ target: targetEl, title: '标题', description: '描述' }]
</script>
<template>
<div ref="targetEl">目标元素</div>
<Tour v-model:open="isOpen" v-model:current="current" :steps="steps" />
</template>Q: 如何在最后一步之后自动执行某些逻辑?
A: 监听 @finish 事件即可。该事件在用户完成所有步骤并点击"结束"按钮时触发。同时 @close 事件也会在跳过和完成两种情况下触发,适合统一处理导览关闭后的清理逻辑。