应采用「currentStep + 规则引擎」驱动多步骤问卷跳转,而非依赖data-tab硬跳;规则表达式(如Q3==='其他')由沙箱Function执行,switchToStep仅更新状态与焦点,支持非线性切换、数据持久化及Worker预计算。

直接用原生 HTML + JS 实现多步骤问卷的标签页条件分支切换,核心不是“让 Tab 动起来”,而是「把跳转逻辑从 UI 层抽离出来,交给纯数据规则驱动」。否则一加个“Q3 选‘其他’就跳到 Q7”,就得在 JS 里硬写 if 分支、手动 click() 某个 tab 按钮——维护爆炸,且无法回溯、无法校验、无法和后端规则对齐。
为什么不能靠 data-tab 硬跳?
很多人写问卷时,给每个步骤 tab 加 data-tab="step3",再用 JS 找到对应按钮触发 click。这看似可行,但实际踩坑极多:
- 点击事件会触发完整生命周期(focus、animation、scroll),而问卷跳转只需状态变更,不该带副作用
- 用户按键盘方向键切换 tab 时,
click()不生效,无障碍链路断裂 - 条件分支嵌套后(比如“Q2=是 → Q4 显示 → Q4>5 → 跳 step6”),硬跳逻辑迅速变成意大利面条代码
-
data-tab是静态标识,不承载计算语义;它适合“点哪个显哪个”,不适合“答完这题该去哪”
用 currentStep + ruleEngine 控制跳转
真正可维护的做法,是把问卷流程抽象成「当前步骤索引 + 规则表」,所有跳转由规则引擎统一判定,JS 只负责执行显隐和焦点转移:
- 定义
currentStep = 0,初始指向第一个 tab 面板 - 每道题的 DOM 元素上加
data-rule,值为可安全求值的表达式,例如:data-rule="Q3==='其他' && Q5>18" - 提交/失焦/选项变化时,收集当前所有题目的值为一个对象(如
{Q3: '其他', Q5: 22}),传给规则函数 - 规则函数遍历所有
data-rule,找到第一个返回true的目标步骤 ID,返回其索引或面板 key - JS 不调用
.click(),而是直接调用switchToStep('step7'),该函数只更新 class、aria-hidden和焦点
示例规则判定函数(不依赖 eval):
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
function evaluateRule(ruleStr, answers) {
try {
// 用 Function 构造器沙箱执行,禁止访问外部作用域
const fn = new Function('data', `return ${ruleStr}`);
return fn(answers);
} catch (e) {
console.warn('Invalid rule:', ruleStr, e);
return false;
}
}
Tab 面板必须支持非线性激活
标准 tab 切换默认是顺序前进/后退,但问卷常需「从 step5 直接跳 step2 回填」或「step8 提交后跳回 step1 并清空」。这就要求面板本身不依赖 DOM 顺序或索引绑定:
- 每个面板用
data-step-id="step2",而非id="tab2"或data-tab="2"—— ID 容易冲突,数字索引无法语义化 - 激活函数
switchToStep('step2')应能处理任意目标,包括未渲染的面板(比如 step2 还没加载,就先占位、异步 fetch 内容) - 面板内含表单时,切换前需保存当前输入(
input.value或textarea.value),切换后再恢复,否则用户输一半跳走就丢数据 - 别用
display: none隐藏未激活面板:含或的步骤会被强制暂停;改用visibility: hidden+position: absolute占位,并设aria-hidden="true"
Worker 里跑规则判定真的可行吗?
可以,但仅限于纯计算场景:
- ✅ 适合:解析并批量执行上百条
data-rule字符串、预计算后续所有可达步骤、校验整份答卷完整性 - ❌ 不适合:读取
input.checked、触发focus()、修改aria-selected、调用scrollIntoView() - 主线程收集当前答案对象后,用
postMessage发给 Worker;Worker 返回推荐的nextStepId;主线程再执行显隐和焦点逻辑 - 注意:Worker 中无法访问
dataset,所以规则字符串必须提前序列化好(比如JSON.stringify(rules))再传入,不能现场 querySelectorAll
最易被忽略的一点:规则表达式里的变量名(如 Q3)必须和你收集的答案对象 key 完全一致,大小写、下划线、空格一个都不能错;建议在初始化阶段做一次 schema 校验,而不是等用户答到第 12 题才报 ReferenceError: Q3 is not defined。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










