- 前端
- UI组件
【免费下载链接】react-joyride
Create guided tours in your apps
导读
React Joyride 是 React 生态中用于创建引导式产品演示(Guided Tour / Onboarding Walkthrough)的开源库,本仓库即其 v3 版本源码。本文以 skills/react-joyride/references/api-props-options.md 为骨架,系统讲解Props、SharedProps、Options(30+ 字段)、Locale、FloatingOptions与Styles六大 API 的全部配置项,并结合 src/types、src/defaults.ts、src/styles.ts 等源码文件揭示每个参数的默认值、类型约束与底层实现逻辑。读完本文,你将能精准地为useJoyride()钩子与<Joyride>组件配置任意引导流程,完成从颜色主题到浮层定位的全方位定制。
一、API 概览:Props 与 SharedProps
1.1 Props:Joyride 与 useJoyride 的顶层配置
Props是<Joyride>组件与useJoyride()钩子共用的顶层配置类型,其完整定义见 src/types/props.ts:
type Props = SharedProps & { continuous?: boolean; // 是否顺序播放(配合 Next 按钮),默认 false debug?: boolean; // 是否向控制台输出日志,默认 false initialStepIndex?: number; // 非受控模式的起始步骤索引,默认 0 nonce?: string; // 内联样式(inline styles)的 CSP nonce onEvent?: EventHandler; // (data: EventData, controls: Controls) => void options?: Partial<Options>; // 所有步骤的全局默认选项 portalElement?: string | HTMLElement; // 将浮层渲染到指定元素内 run?: boolean; // 启动 / 停止引导,默认 false scrollToFirstStep?: boolean; // 启动时是否滚动到第一步,默认 false stepIndex?: number; // 受控模式:由外部管理步骤索引 steps: Array<Step>; // 必填:引导步骤列表 }各字段要点:
run与continuous:run: true触发引导启动;continuous开启后 Next 按钮会按顺序自动推进步骤,是"产品演示"模式的核心开关。两者默认值(false)可在 src/defaults.ts 的defaultProps中确认。debug:官方技能文档(SKILL.md)将其定位为"最强大的排障工具",开启后会在控制台输出生命周期切换、状态变更与事件派发的完整日志,排障时应首先打开它。stepIndex与initialStepIndex:一旦传入stepIndex,Joyride 即进入受控模式(controlled标志为 true),initialStepIndex被忽略(源码注释明确标注"controlled mode ignores initialStepIndex");此时必须由父组件在onEvent中自行更新索引。portalElement:类型为SelectorOrElement(CSS 选择器字符串或 HTMLElement),可将工具提示渲染到指定容器内,便于配合 Modal / Portal 类弹层使用。nonce:为内联<style>注入 CSP nonce,用于启用严格 Content Security Policy 的环境。options:所有步骤共享的默认选项,可在单个步骤上覆盖(步骤级覆盖全局,见下文 Options 一节)。
1.2 SharedProps:Props 与 Step 的公共配置
SharedProps同时被Props和Step继承,因此以下配置既可以在组件/钩子层面设置,也可以在单个步骤中设置:
type SharedProps = { arrowComponent?: ElementType<ArrowRenderProps>; // 自定义箭头组件 beaconComponent?: ElementType<BeaconRenderProps>; // 自定义信标组件 floatingOptions?: Partial<FloatingOptions>; // 浮层定位配置 loaderComponent?: ElementType<LoaderRenderProps> | null; // 自定义加载器;null 禁用 locale?: Locale; // 工具提示文案 styles?: PartialDeep<Styles>; // 任意 UI 元素的样式覆盖 tooltipComponent?: ElementType<TooltipRenderProps>; // 自定义工具提示组件 }自定义组件均接收各自的 Render Props(详见 src/types/components.ts 及 api-events-components.md),例如TooltipRenderProps提供backProps、primaryProps、tooltipProps等需展开到按钮/容器上的属性。特别地,loaderComponent: null可彻底禁用加载器。
二、Options:30+ 配置项的完整参考
Options的全部字段既可经optionsprop 全局设置,也可在单个步骤上按步骤覆盖("Per-step values override global")。其完整类型定义在 src/types/common.ts,所有默认值集中在 src/defaults.ts 的defaultOptions中,两处内容可互相印证。以下按六类逐一详解。
2.1 外观(Appearance)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
backgroundColor | string | '#ffffff' | 工具提示背景色 |
primaryColor | string | '#000000' | 主按钮与信标颜色 |
textColor | string | '#000000' | 工具提示文字颜色 |
overlayColor | string | '#00000080' | 遮罩层(backdrop)颜色 |
arrowColor | string | '#ffffff' | 箭头填充色 |
width | string \| number | 380 | 工具提示宽度 |
zIndex | number | 100 | 遮罩与工具提示的 z-index |
从源码实现看,这些颜色会直接注入 src/styles.ts 的默认样式:overlay的backgroundColor取自step.overlayColor,tooltip的背景与文字分别取自step.backgroundColor与step.textColor,beaconInner与buttonPrimary使用step.primaryColor(src/styles.ts)。一个实用细节:width为数字时,若视口宽度小于该值,Joyride 会自动将其收窄为window.innerWidth - 30,防止移动端溢出(src/styles.ts)。
2.2 箭头(Arrow)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
arrowBase | number | 32 | 箭头底边宽度(像素) |
arrowSize | number | 16 | 箭头高度/深度(像素) |
arrowSpacing | number | 12 | 箭头距工具提示边缘的距离 |
这三个值构成箭头的几何参数,并作为ArrowRenderProps的base/size传给自定义箭头组件(参考 api-events-components.md 中ArrowRenderProps定义:{ base, placement, size })。
2.3 信标(Beacon)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
beaconSize | number | 36 | 信标直径(像素) |
beaconTrigger | 'click' \| 'hover' | 'click' | 从信标打开工具提示的交互方式 |
beaconSize决定默认信标的宽高(height/width: step.beaconSize),beaconTrigger: 'hover'可将悬停作为打开方式。信标默认采用"内层实心圆 + 外层脉冲环"的双层结构,动画由joyride-beacon-inner/joyride-beacon-outer两个关键帧驱动(src/styles.ts)。
2.4 遮罩与聚光(Overlay & Spotlight)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
hideOverlay | boolean | false | 是否不显示遮罩层 |
blockTargetInteraction | boolean | false | 是否阻止目标元素上的指针事件 |
spotlightRadius | number | 4 | 聚光"挖孔"的圆角 |
spotlightPadding | number \| SpotlightPadding | 10 | 目标周围的聚光内边距 |
interface SpotlightPadding { top?: number; right?: number; bottom?: number; left?: number; }spotlightPadding既可以是统一数值,也可以是四个方向独立的对象。值得说明的是blockTargetInteraction:开启后,即使目标元素被"挖孔"透出,其上的点击事件也会被遮罩拦截——这适用于希望在引导期间禁止用户操作高亮元素的场景。
2.5 按钮与交互(Buttons & Interactions)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
buttons | ButtonType[] | ['back','close','primary'] | 工具提示中显示的按钮 |
closeButtonAction | 'close' \| 'skip' | 'close' | 关闭按钮行为 |
overlayClickAction | 'close' \| 'next' \| false | 'close' | 点击遮罩的行为 |
dismissKeyAction | 'close' \| 'next' \| false | 'close' | ESC 键行为 |
showProgress | boolean | false | 是否显示"N of Total"进度 |
ButtonType = 'back' | 'close' | 'primary' | 'skip'。
需要特别说明的是,src/types/common.ts 中这三个"动作"字段的实际类型比参考文档更宽:
closeButtonAction实际还支持'replay'(重放当前步骤);overlayClickAction同样支持'replay',false表示禁用遮罩点击;dismissKeyAction支持'close' | 'next' | 'replay' | false,其中'next'在 continuous 模式下会跳过信标直接推进,false表示禁用 ESC。
若想在默认三个按钮之外追加"跳过"按钮,只需在buttons中加入'skip'。showProgress: true时,主按钮文案会切换为locale.nextWithProgress,并实时替换{current}/{total}占位符(见下文 Locale)。
2.6 滚动(Scroll)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
skipBeacon | boolean | false | 跳过信标,直接显示工具提示 |
skipScroll | boolean | false | 不滚动到目标元素 |
scrollDuration | number | 300 | 滚动动画时长(毫秒) |
scrollOffset | number | 20 | 距元素的滚动偏移量 |
offset | number | 10 | 工具提示与聚光之间的间距 |
scrollOffset用于为固定头部/悬浮元素预留空间;offset则控制工具提示与高亮区域之间的视觉距离。相关实现可参考 src/hooks/useScrollEffect.ts(滚动动画与scroll:start/scroll:end事件派发)。
2.7 时序与异步(Timing & Async)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
before | BeforeHook | - | (data: TourData) => Promise<void>,步骤显示前执行 |
after | AfterHook | - | (data: TourData) => void,步骤结束后执行(fire-and-forget) |
beforeTimeout | number | 5000 | before钩子的最大等待时间(0 = 不限时) |
targetWaitTimeout | number | 1000 | 目标元素出现的最大等待时间(0 = 不等待) |
loaderDelay | number | 300 | 显示加载器前的延迟(毫秒) |
disableFocusTrap | boolean | false | 是否禁用工具提示的焦点陷阱 |
before与after的签名类型定义于 src/types/common.ts:BeforeHook必须返回 Promise,AfterHook则无需阻塞(fire-and-forget)。beforeTimeout/targetWaitTimeout置0可分别取消钩子超时与目标轮询;等待期间,经过loaderDelay后加载器会出现(参考 src/components/Loader.tsx)。
三、Locale:工具提示文案国际化
Locale接口定义(src/types/common.ts)与默认文案(src/defaults.ts):
interface Locale { back?: ReactNode; // 'Back' close?: ReactNode; // 'Close' last?: ReactNode; // 'Last' next?: ReactNode; // 'Next' nextWithProgress?: ReactNode; // 'Next ({current} of {total})' open?: ReactNode; // 'Open the dialog' skip?: ReactNode; // 'Skip' }关键点:nextWithProgress中的{current}和{total}是渲染时替换的占位符——{current}替换为当前步骤序号,{total}替换为总步骤数。由于字段类型是ReactNode,文案可以是任意 React 节点(如<strong>下一步</strong>),这为多语言与富文本定制留出了充分空间。open字段是信标按钮的无障碍标签(aria-label),默认'Open the dialog'。
四、FloatingOptions:基于 Floating UI 的浮层定位
Joyride v3 的定位系统构建于@floating-ui/react-dom之上,FloatingOptions用于精细控制定位行为(类型定义见 src/types/floating.ts):
interface FloatingOptions { autoUpdate?: Partial<AutoUpdateOptions>; // autoUpdate 配置(滚动监听、尺寸监听、动画帧等) beaconOptions?: { offset?: number }; // 信标偏移(默认 -18) flipOptions?: Partial<FlipOptions> | false; // flip 中间件(false 禁用翻转) hideArrow?: boolean; // 隐藏箭头(默认 false) middleware?: Array<Middleware>; // 追加的 Floating UI 中间件 onPosition?: (data: PositionData) => void; // 每次定位计算后的回调 shiftOptions?: Partial<ShiftOptions>; // shift 中间件配置 strategy?: 'fixed' | 'absolute'; // 由 step.isFixed 自动推断 }flipOptions:默认开启翻转(含 crossAxis: false、padding 20、左右方向的智能 fallbackPlacements),传false可强制工具提示不翻转——适合需要严格固定方位、宁可溢出也不换位的场景。shiftOptions:默认 padding 10,负责把工具提示移回视口内,防止溢出。beaconOptions.offset:信标相对目标的内外偏移,默认-18(src/defaults.ts)。strategy:默认根据步骤的isFixed自动选择——isFixed: true用'fixed',否则'absolute'。onPosition:回调参数PositionData包含{ middlewareData, placement, x, y },可用于调试或驱动自定义动画。hideArrow:隐藏箭头;居中放置(placement: 'center')时箭头本就自动隐藏。middleware:可在默认中间件链(offset、flip/autoPlacement、shift、arrow)之后追加自定义中间件。
五、Styles:逐元素 CSS 覆盖
Styles允许对任意 UI 元素做 CSS 覆盖,键列表(完整定义见 src/types/common.ts):
interface Styles { arrow: CSSProperties; beacon: CSSProperties; beaconInner: CSSProperties; beaconOuter: CSSProperties; beaconWrapper: CSSProperties; buttonBack: CSSProperties; buttonClose: CSSProperties; buttonPrimary: CSSProperties; buttonSkip: CSSProperties; floater: CSSProperties; loader: CSSProperties; overlay: CSSProperties; spotlight: SVGAttributes<SVGPathElement>; // 注意:聚光样式是 SVG Path 属性 tooltip: CSSProperties; tooltipContainer: CSSProperties; tooltipContent: CSSProperties; tooltipFooter: CSSProperties; tooltipFooterSpacer: CSSProperties; tooltipTitle: CSSProperties; }- 使用
PartialDeep<Styles>,只需覆盖需要的键,未覆盖部分保留默认值。 spotlight的类型是SVGAttributes<SVGPathElement>而非CSSProperties——因为聚光"挖孔"是通过 SVG Path 实现的(参考 src/components/Overlay.tsx),设置圆角等视觉属性时应遵循 SVG 属性语法。- 默认样式的完整实现集中在 src/styles.ts:包括按钮样式族(
buttonBack用主色文字并右对齐、buttonPrimary主色背景、buttonClose右上角绝对定位、buttonSkip小号文字)、floater的drop-shadow滤镜与opacity 0.3s过渡、loader的zIndex: step.zIndex + 1等。 - 合并顺序为
defaultStyles → props.styles → step.styles(src/styles.ts 中deepMerge的调用顺序),因此步骤级样式优先级最高,可用来做"某一步特别强调"的局部主题。
一个实用的完整主题示例(来自 SKILL.md):
styles: { tooltip: { borderRadius: 12 }, buttonPrimary: { backgroundColor: '#1976d2' }, buttonBack: { color: '#666' }, spotlight: { borderRadius: 8 }, }六、配置生效层级与实战建议
综合上文,Joyride v3 的配置生效遵循清晰的层级规则:
- 内置默认值:
defaultOptions(src/defaults.ts)、defaultFloatingOptions、defaultLocale构成兜底; - 组件/钩子级配置:
Props.options、Props.locale、Props.styles、Props.floatingOptions等全局覆盖默认值; - 步骤级配置:每个
Step继承SharedProps与Partial<Options>(api-step-state-controls.md),可逐步骤覆盖全局配置——这是"引导中某几步使用特殊配色/按钮/定位"的标准做法。
StepMerged是默认值应用完成后的规范化步骤(所有 Options 字段变为必填、spotlightPadding展开为四向对象、styles完全解析),它正是你在事件回调与自定义组件 props 中实际收到的对象。
三种主题化手段的取舍
- 颜色 Options(最简):只改
primaryColor/backgroundColor/textColor/overlayColor/arrowColor,适合快速换肤; - Styles 覆盖(中等):按
tooltip/buttonPrimary/beacon等键做细粒度 CSS 调整; - 自定义组件(完全控制):
tooltipComponent/beaconComponent/arrowComponent/loaderComponent接收 Render Props 并自行渲染,适合品牌化定制。
七、配置调试速查
- 一切从
debug: true开始:控制台会输出生命周期阶段(init → ready → beacon_before → beacon → tooltip_before → tooltip → complete)与每个动作(next/prev/close/skip)的完整日志,可定位配置未生效或流程卡住的环节(SKILL.md)。 - 工具提示不出现:确认目标元素可见(非
display: none/visibility: hidden/ 零尺寸),必要时调大targetWaitTimeout;检查祖先节点是否有overflow: hidden裁剪。 - 滚动异常:固定头部场景调大
scrollOffset(默认 20);某步不想滚动时设skipScroll: true;首步在视口外时开启scrollToFirstStep: true。 - 受控模式卡住:只要传入了
stepIndex就进入受控模式,必须在onEvent中同步更新stepIndex(处理step:after与error:target_not_found),且go()/reset()在该模式下不可用。 - 验证默认值:所有字段的权威默认值请以 src/defaults.ts 为准——例如
dismissKeyAction实际支持'replay'取值,closeButtonAction/overlayClickAction同样如此,这些细节在类型源码中有最完整的定义。
仓库内还提供了丰富的可运行示例与测试来验证上述配置的实际效果:useJoyride的渲染与返回值见 src/hooks/useJoyride.tsx,钩子级测试见 test/hooks/useJoyride.spec.tsx,Options 的默认值断言见 test/modules/step.spec.ts,样式合并与快照见 test/styles.spec.ts。此外,website/src/app/demos 下提供了 overview、carousel、modal 等真实演示页,是观察各配置项实际效果的直观参考。
- 前端
- UI组件
【免费下载链接】react-joyride
Create guided tours in your apps
相关推荐
Garnet 配置系统完全指南:Options、配置文件与命令行解析机制深度解析
Garnet 配置系统完全指南:Options、配置文件与命令行解析机制深度解析 Garnet 作为微软研究院推出的高性能远程缓存存储系统,其全部可配置项最终都
缓存KV存储后端React Styleguidist 主题定制实战:基于 themed 示例深度解析 theme 与 styles 配置
React Styleguidist 主题定制实战:基于 themed 示例深度解析 theme 与 styles 配置 导读 本篇文章以仓库中的 exampl
开发工具前端ngx-formly 核心配置详解:Properties 与 Options 深度解析
ngx formly 核心配置详解:Properties 与 Options 深度解析 引言:为什么需要深入了解 Formly 配置? 在 Angular 表单
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考