分步表单应使用单个包裹多个(每步一个),各设唯一data-step标识且保留在dom中;校验时仅遍历当前可见步骤内required字段调用checkvalidity(),避免form.checkvalidity()误检隐藏字段。

分步表单的 DOM 结构怎么组织才方便校验?
分步表单本质是「隐藏非当前页 + 按需校验当前页」,不是靠 JS 模拟跳转,而是用 display: none 或 hidden 属性控制可见性。关键在于每页 fieldset 或 div 必须有唯一标识(比如 data-step="1"),且所有 input 保留在同一 form 内——否则 form.checkValidity() 会漏掉隐藏字段,校验失效。
- 当前步骤容器加
aria-hidden="true",非当前页加 tabindex="-1" 避免键盘焦点误入
- 所有
input 保留 required 属性,但校验只触发在 visible 步骤内
- 不要用多个独立
form 标签,否则提交时无法一次性收集全部数据
点击“下一步”时如何只校验当前页?
不能直接调用 form.reportValidity(),它会校验所有 required 字段(包括隐藏的)。正确做法是:先筛选出当前步骤内可见且带 required 的元素,再逐个调用 checkValidity()。
const currentStep = document.querySelector('[data-step="2"]:not([hidden])');
const requiredFields = currentStep.querySelectorAll('input[required]:not([type="hidden"]), select[required], textarea[required]');
const isValid = Array.from(requiredFields).every(el => el.checkValidity());
<p>if (!isValid) {
// 找到第一个无效字段并聚焦
const firstInvalid = requiredFields[0];
firstInvalid.focus();
firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
}</p>
- 注意排除
type="hidden",它虽是 input 但不参与用户输入校验
-
checkValidity() 返回 false 时,浏览器自动触发 invalid 事件,可监听做自定义提示
- 不要依赖
form.elements,它包含所有字段(含隐藏页),遍历效率低且逻辑易错
后端校验和前端校验怎么对齐字段范围?
前端分步校验只控制流程,后端必须按完整表单校验,且字段名不能因分步而拆散。常见坑是:前端用 name="step1.email" 这类命名,导致后端解析失败或重复校验。
所有字段用语义化 name,如 name="email"、name="phone",不要加步骤前缀
提交时仍用单次 POST,后端按完整字段集校验,不区分“哪一步填的”
若需记录填写进度,额外传 current_step=2 这类参数,不混入业务字段
前端校验提示文案(如“邮箱格式错误”)必须和后端返回的错误码/消息保持一致,避免用户看到两套说法
后端返回的字段级错误(如 {"email": "已被注册"})需能精准映射到对应 input[name="email"],否则无法定位高亮
移动端键盘弹起后,“下一步”按钮被顶出视口怎么办?
iOS Safari 和部分安卓 WebView 在软键盘弹出时不会自动滚动页面,导致底部按钮不可见,用户卡住。这不是校验逻辑问题,但直接影响流程完成率。
不要用 position: fixed 把按钮钉在底部,键盘弹出会遮挡
给当前步骤容器加 scroll-margin-bottom: 60px,配合 focus 时调用 element.scrollIntoView()
更稳妥的是监听 focusin 事件,在 input 获焦后延迟 100ms 执行 scrollIntoView({ block: 'nearest' })
避免在 resize 事件里做 scroll 操作,iOS 键盘收起会频繁触发,造成抖动
如果用第三方 UI 库(如 Bootstrap、Element Plus),确认其 step 组件是否内置了键盘适配,没做就别硬套
aria-hidden="true",非当前页加 tabindex="-1" 避免键盘焦点误入 input 保留 required 属性,但校验只触发在 visible 步骤内 form 标签,否则提交时无法一次性收集全部数据 form.reportValidity(),它会校验所有 required 字段(包括隐藏的)。正确做法是:先筛选出当前步骤内可见且带 required 的元素,再逐个调用 checkValidity()。
const currentStep = document.querySelector('[data-step="2"]:not([hidden])');
const requiredFields = currentStep.querySelectorAll('input[required]:not([type="hidden"]), select[required], textarea[required]');
const isValid = Array.from(requiredFields).every(el => el.checkValidity());
<p>if (!isValid) {
// 找到第一个无效字段并聚焦
const firstInvalid = requiredFields[0];
firstInvalid.focus();
firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });
}</p>
- 注意排除
type="hidden",它虽是input但不参与用户输入校验 -
checkValidity()返回false时,浏览器自动触发invalid事件,可监听做自定义提示 - 不要依赖
form.elements,它包含所有字段(含隐藏页),遍历效率低且逻辑易错
后端校验和前端校验怎么对齐字段范围?
前端分步校验只控制流程,后端必须按完整表单校验,且字段名不能因分步而拆散。常见坑是:前端用 name="step1.email" 这类命名,导致后端解析失败或重复校验。
所有字段用语义化 name,如 name="email"、name="phone",不要加步骤前缀
提交时仍用单次 POST,后端按完整字段集校验,不区分“哪一步填的”
若需记录填写进度,额外传 current_step=2 这类参数,不混入业务字段
前端校验提示文案(如“邮箱格式错误”)必须和后端返回的错误码/消息保持一致,避免用户看到两套说法
后端返回的字段级错误(如 {"email": "已被注册"})需能精准映射到对应 input[name="email"],否则无法定位高亮
移动端键盘弹起后,“下一步”按钮被顶出视口怎么办?
iOS Safari 和部分安卓 WebView 在软键盘弹出时不会自动滚动页面,导致底部按钮不可见,用户卡住。这不是校验逻辑问题,但直接影响流程完成率。
不要用 position: fixed 把按钮钉在底部,键盘弹出会遮挡
给当前步骤容器加 scroll-margin-bottom: 60px,配合 focus 时调用 element.scrollIntoView()
更稳妥的是监听 focusin 事件,在 input 获焦后延迟 100ms 执行 scrollIntoView({ block: 'nearest' })
避免在 resize 事件里做 scroll 操作,iOS 键盘收起会频繁触发,造成抖动
如果用第三方 UI 库(如 Bootstrap、Element Plus),确认其 step 组件是否内置了键盘适配,没做就别硬套
所有字段用语义化 name,如 name="email"、name="phone",不要加步骤前缀
提交时仍用单次 POST,后端按完整字段集校验,不区分“哪一步填的”
若需记录填写进度,额外传 current_step=2 这类参数,不混入业务字段
前端校验提示文案(如“邮箱格式错误”)必须和后端返回的错误码/消息保持一致,避免用户看到两套说法
后端返回的字段级错误(如 {"email": "已被注册"})需能精准映射到对应 input[name="email"],否则无法定位高亮
不要用
position: fixed把按钮钉在底部,键盘弹出会遮挡给当前步骤容器加
scroll-margin-bottom: 60px,配合focus时调用element.scrollIntoView()更稳妥的是监听
focusin事件,在input获焦后延迟 100ms 执行scrollIntoView({ block: 'nearest' })避免在
resize事件里做 scroll 操作,iOS 键盘收起会频繁触发,造成抖动如果用第三方 UI 库(如 Bootstrap、Element Plus),确认其
step组件是否内置了键盘适配,没做就别硬套
分步校验真正的复杂点不在 JS 逻辑,而在 DOM 可访问性、移动端行为一致性、前后端字段契约这三处。漏掉任意一个,用户都可能在最后一步提交时才发现之前填的全白费。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











