Skip to content

Questionnaire 多步问答 ​

步骤驱动的表单流程编排组件:步骤头 + 进度(「第 n / m 步」)+ 每步内容面板 + 单步校验门控。适合向导式表单 / 问卷 / 多步结算等场景。校验复用 oas-form 内核——每步面板内放一个 <oas-form>,下一步前对当前步校验、未过不放行;回退不校验、面板常驻不卸载(已填值保留)。

边界:线性门控 + 可选步跳过 + oas-before-change 宿主自定义跳转 + 条件分支走宿主组合通道(hidden 数据位 + oas-before-change + oas-values-change,见下文);谓词 / 表达式引擎不内置(宿主持有全量答案数据,分支决策留在宿主可 veto、可测试的应用层)。起始页/完成页暂不内置;草稿持久化请用 current + getValues() 自行实现。

基础用法 ​

steps 传步骤数组({ key?, title, description?, optional?, hidden? }),每步内容经命名插槽关联:有 key 用 slot="step-<key>",无 key 用 slot="step-<index>"。末步主按钮自动变为「完成」,点击重校全部参与步后派发 oas-submit(detail.values 为跨步汇总值)。取值与校验同口径——只含「参与步」(非 hidden 且未被跳过的步);需全量数据的宿主可读取各面板内的 oas-form 自行汇总。

基础多步问答

支付宝微信支付

信息确认无误后,点击「完成」提交。

单步校验门控 ​

下一步前对当前步 oas-form 校验(委托其 validate()),未过不放行并派发 oas-step-validate(detail: { index, key?, valid, errors });回退不校验(不会被错误困在当前步)。validation="false" 关闭门控(纯导航)。

未填不放行

校验通过后才能到达这一步。

可选步跳过 ​

步骤声明 optional: true 后,导航区出现「跳过本步」按钮:跳过不触发校验、直接前进,派发 oas-skip(detail: { index, key? })。被跳过的步退出参与步集合——其值不进 getValues() / oas-submit、也不再参与提交重校;重新回到该步(回退 / 头部点击 / goto())即恢复参与,reset() 清全部跳过记录。

可选步(Skip)

最后一步。

宿主拦截跳步(oas-before-change) ​

任何跳步(按钮 / 头部点击 / next() / prev() / goto() / 跳过)前派发可取消事件 oas-before-change(detail: { index, key?, from }),宿主 preventDefault() 可否决——也是自定义分支跳转的挂点。linear="false" 关闭线性禁跳后,头部任意步可点。

preventDefault 否决跳步

第一步内容

第二步内容

确认页(演示中被宿主拦截,进不来)

条件分支(按答案跳步) ​

条件分支走宿主组合通道,不内置谓词引擎:宿主监听 oas-values-change 拿到答案,按业务规则改写 steps 翻转 hidden 位即生效——被隐藏步退出头部与进度、next() 自动跳过、其值退出取值与校验口径。若翻转的是用户所在步,组件自动把 current 对齐到最近可见步并派发 oas-change(宿主无需再手动跳转)。分支决策留宿主的好处:规则可单测、可在 oas-before-change 里再 veto、避免在组件内重造一套表达式语言。

按答案隐藏/恢复步骤

需要开票不需要

最后一步。

切换动画(animated) ​

animated 开启题目切换过渡:新面板按导航方向滑入 + 淡入(前进自行尾侧、后退自行首侧;只动 transform/opacity,合成器友好);prefers-reduced-motion: reduce 用户自动降级为无动画。时长经 CSS 变量 --oas-questionnaire-anim-duration 覆盖(缺省 --oas-transition-base);RTL 布局下滑入方向自动镜像。

animated 切换过渡(点下一步/上一步观察滑入方向)

点「下一步」:本面板按导航方向滑入 + 淡入。

前进与后退的滑入方向相反;回到第一步用「上一步」观察。

最后一步。

reset()

键盘快捷导航(shortcuts) ​

shortcuts 开启键盘切步:Alt+←/→ 在组件内任何位置(含输入框内)切上/下一步,并吞掉默认行为(防浏览器历史导航);裸 ←/→(无修饰键)仅在焦点不在输入框/文本域/可编辑区等控件时切步(不劫持光标与控件自身键盘),点击面板空白处焦点落在组件容器上同样可达。触发走与按钮相同的门控链路(当前步未过校验不放行);物理方向映射(→ 前进 / ← 后退),RTL 不镜像,与浏览器历史键惯例一致。

shortcuts 键盘切步(点进组件内按 Alt+←/→ 试试)

焦点在面板空白处时,裸 ←/→ 也能切步。

最后一步。

受控 current 与方法 ​

current 双向:内部跳步写回属性,外部设置即时同步。命令式方法 next() / prev() / goto(index) / validate() / submit() / getValues() / reset() 覆盖全部导航与取值场景。

事件命名提示:步骤面板内字段自身的 oas-change / oas-input 等事件会冒泡穿出 questionnaire。字段 oas-change 与切步 oas-change 同名——监听切步时请按 detail.index 过滤(字段事件不含 index);字段值变化推荐监听 oas-values-change(detail: { name, value, values })。

外部控制与取值

prev()next()goto(2)validate()getValues()reset()

进度形态 ​

progress-variant 三档:both(默认,文本 + 进度条)/ text(只留「第 n / m 步」)/ bar(只留进度条);progress="false" 整体隐藏。进度条走 role="progressbar" + aria-valuenow/min/max,读屏可朗读。

progress-variant 三档 + 隐藏

both(默认)

文本 + 进度条

丙

text

只留进度文本

丙

bar

只留进度条

丙

回退值保留与重置 ​

面板常驻不卸载(仅切 hidden):前进再回退,已填值不丢。reset() 全部步骤回到初始值、清错误态、回第一步,不派发事件。

回退不丢值 + reset()

点「上一步」回到第一步,已改的值还在。

reset()

自定义导航区(hide-header / hide-nav) ​

hide-header / hide-nav 隐藏内置步骤头 / 导航区,宿主可完全自组合(进度与面板仍由组件驱动)。

hide-nav + 外部按钮驱动

内置导航已隐藏

由外部按钮驱动

上一步下一步

纯导航模式(validation / progress / hide-header) ​

validation="false" 关闭单步门控(纯导航,未填也放行);progress="false" 隐藏进度区;hide-header 隐藏内置步骤头。三者可独立开启,也可组合成极简流程(只剩面板与导航按钮)。

纯导航:无门控 / 无进度 / 无头部

未填也能到达本步(门控已关闭)。

API ​

方法 ​

方法说明
next()下一步:先对当前步 oas-form 校验(validation="false" 时跳过),通过才前进;异步校验在途时重入直接拒绝。返回 Promise<boolean>
prev()上一步:不校验(回退不被错误困住)。返回 boolean
goto(index)直跳任意步:不走单步门控;越界夹取,落在 hidden 步时向后解析。返回 boolean
validate()校验全部参与步(非 hidden 且未跳过;顺序执行,逐步派发 oas-step-validate),返回 Promise<boolean>
submit()提交:重校全部参与步(含早期步),全过才派发 oas-submit(detail.values 为跨步汇总值,仅参与步——hidden / 已跳过步不计入)。返回 Promise<boolean>
getValues()跨步值汇总(参与步口径,与校验同集合):各参与步 oas-form 当前值按步序深合并(与单表 submit() 的 detail.values 同口径,零交互的 value 属性预填同样计入);需全量数据可读各面板内的 oas-form。返回 Record<string, unknown>
reset()全部步骤 form 重置回初始值、清错误态、current 回 0;不派发任何事件

oas-questionnaire ​

属性 ​

属性说明类型默认值
animated题目切换过渡(opt-in,存在且非 "false" 时开启):新面板按导航方向滑入 + 淡入(只动 transform/opacity);prefers-reduced-motion: reduce 自动降级为无动画;RTL 滑入方向自动镜像boolean—
current当前步索引(0 起,受控双向:内部跳步写回、外部设置即时同步);非法值回落 0,越界夹取string0
finish-text末步主按钮文案(覆盖 locale 缺省「完成」)——
hide-header隐藏内置步骤头(宿主自组合)boolean—
hide-nav隐藏内置导航区(宿主自组合)boolean—
linear线性模式(默认开,linear="false" 关闭):未来步头部禁点;关闭后任意步可点(仍走 oas-before-change 拦截)stringtrue
next-text「下一步」按钮文案(覆盖 locale 缺省)——
prev-text「上一步」按钮文案(覆盖 locale 缺省)——
progress进度区显隐(progress="false" 隐藏)stringtrue
progress-variant进度形态:both(默认,文本+进度条)/ text / bar;非法值回落 bothstringboth
shortcuts键盘快捷导航(opt-in,存在且非 "false" 时开启):Alt+←/→ 在组件内任何位置切上/下一步(吞掉默认行为防浏览器历史导航);裸 ←/→ 仅在焦点不在输入/可编辑控件时生效(不劫持光标)boolean—
size尺寸档位:xs/small/medium/large/xl(标题字号密度;非法值回落 medium + 告警一次(同值去重))stringmedium
skip-text「跳过本步」按钮文案(覆盖 locale 缺省)——
steps步骤数据 JSON [{ key?, title, description?, optional?, hidden? }];非法/空回落 []QuestionnaireStep[] | string[]
validation单步校验门控(默认开,validation="false" 纯导航;submit() 不受此开关影响、始终重校)stringtrue

事件 ​

事件说明
oas-before-change跳步前(按钮 / 头部点击 / next / prev / goto / 跳过)可取消;detail: { index, key?, from },preventDefault() 否决本次跳转
oas-change切步成功后;detail: { index, key? }
oas-skip跳过可选步时;detail: { index, key? }(跳过不触发校验;被跳过的步退出取值/校验口径,重新进入恢复)
oas-step-validate单步校验结束时;detail: { index, key?, valid, errors }
oas-submit末步完成(全部参与步校验通过);detail: { values }(跨步汇总值,仅参与步——hidden / 已跳过步不计入)
oas-values-change内层 oas-form 值变化事件自然冒泡转发(detail: { name, value, values },values 为该步快照);跨步汇总视图用 getValues()

插槽 ​

名称说明
step-<index>步骤内容面板(无 key 的步骤按数组下标关联)
step-<key>步骤内容面板(有 key 的步骤);面板内建议放一个 <oas-form> 承载该步字段与校验规则

CSS 变量 ​

CSS 变量说明默认值
--oas-questionnaire-anim-duration切步动画时长(animated 开启时生效)var(--oas-transition-base, 180ms)
--oas-questionnaire-nav-gap导航区按钮间距var(--oas-space-2)
--oas-questionnaire-progress-bar-bg进度条填充色var(--oas-color-primary)
--oas-questionnaire-progress-bg进度条轨道底色var(--oas-color-bg-hover)

基于 MIT OR Apache-2.0 双许可发布