Skip to content

Tour 导览 ​

新粗野主义风格的分步引导组件。使用 Canvas 局部挖孔遮罩高亮目标元素,配合弹出面板展示步骤说明,支持四方向定位、键盘导航和视口边界约束,帮助用户快速了解界面功能。

预览 ​

Preview
导航
操作区
⚙ 设置

安装 ​

pnpm dlx brutx-vue@latest add tour

用法 ​

基础用法 ​

定义步骤数组,通过 v-model:open 和 v-model:current 控制导览的显示状态和当前步骤:

vue
<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)。

vue
<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 事件响应用户操作:

vue
<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 自定义目标元素滚动到视口时的行为:

vue
<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 ​

ts
interface TourStep {
    target: string | HTMLElement
    title?: string
    description?: string
    placement?: 'top' | 'bottom' | 'left' | 'right'
    mask?: boolean
}
字段类型默认值说明
targetstring | HTMLElement—目标元素,CSS 选择器字符串或 DOM 元素引用(必需)
titlestring—步骤标题
descriptionstring—步骤描述文本
placement'top' | 'bottom' | 'left' | 'right''bottom'弹出面板相对目标元素的显示方向
maskboolean—是否为此步骤显示遮罩,未指定时继承组件级 mask 属性

导出类型 ​

ts
import type { TourStep, TourProps } from 'brutx-ui-vue'

API 参考 ​

Tour — 属性
名称类型默认值说明
steps
必填
TourStep[]
—
按顺序提供导览步骤;每一步通过 CSS 选择器或 HTMLElement 指定目标,并可带标题、说明、显示方向及遮罩设置。
详情

声明类型

TourStep[]

关联类型

TourStep
类型定义 — TourStep
export interface TourStep {
    target: string | HTMLElement
    title?: string
    description?: string
    placement?: 'top' | 'bottom' | 'left' | 'right'
    mask?: boolean
}

默认值详情

未声明默认值
—

来源

types.ts:12

packages/ui/src/components/tour/types.ts

mask
boolean | undefined
true
设置步骤目标之外是否显示遮罩;默认显示,可由当前 TourStep.mask 单独覆盖。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
true

来源

types.ts:13

packages/ui/src/components/tour/types.ts

scrollIntoViewOptions
ScrollIntoViewOptions | undefined
undefined
设置切换步骤前滚动目标元素时传给 scrollIntoView 的选项;未指定时使用 block: center、inline: nearest。
详情

声明类型

ScrollIntoViewOptions | undefined

默认值详情

解析值
undefined

来源

types.ts:14

packages/ui/src/components/tour/types.ts

current
number | undefined
0
当前导览步骤的从 0 开始索引,可通过 v-model:current 受控同步,默认从第一步开始。
详情

声明类型

number | undefined

默认值详情

解析值
0

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

open
boolean | undefined
true
控制导览是否打开,可通过 v-model:open 受控同步;默认打开。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
true

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

Tour — 事件
名称签名或类型说明
@close
[]
用户跳过或完成导览并关闭时发出。
详情

声明类型

[]

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

@update:open
[value: boolean]
导览打开状态变化时发出新布尔值,用于同步 v-model:open。
详情

声明类型

[value: boolean]

字面量

  • false
  • true

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

@finish
[]
用户在最后一步选择结束时发出。
详情

声明类型

[]

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

@update:current
[value: number]
当前步骤变化时发出新索引,用于同步 v-model:current。
详情

声明类型

[value: number]

来源

Tour.vue

packages/ui/src/components/tour/Tour.vue

@skip
[]
用户选择跳过导览时发出。
详情

声明类型

[]

来源

Tour.vue

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:

vue
<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 事件也会在跳过和完成两种情况下触发,适合统一处理导览关闭后的清理逻辑。

蛮力铸就。