必须调用event.preventdefault()阻止表单默认提交,校验逻辑须在submit事件中执行;优先使用input.checkvalidity()和validity api;错误信息需绑定到对应字段并用aria属性增强可访问性;前后端字段名必须严格一致。

submit 事件里阻止默认行为是必须的
表单提交失败却页面跳转或刷新,八成是因为没调用 event.preventDefault()。浏览器原生会把 <form></form> 提交当成一次完整导航,哪怕你写了 JS 验证逻辑,只要没拦住默认动作,后端没收到请求、前端验证也白做。
- 所有自定义校验和提交逻辑,必须包裹在
form.addEventListener('submit', handler)里,不能只监听按钮点击 -
handler函数第一行就该是event.preventDefault(),别等验证完再加——验证失败时容易漏掉 - 如果用了
onsubmit="return false"内联写法,要确认返回值严格为false,JS 表达式结果为falsy(比如空字符串、0)并不等价
input 元素的 validity API 比正则更可靠
很多人一上来就手写正则校验邮箱、手机号,但浏览器原生的 checkValidity() 和 validity 对象已经覆盖了大部分场景,而且自动适配语义化属性(required、type="email"、minlength 等),还能触发原生提示气泡。
-
input.checkValidity()返回布尔值,比手动取value再跑正则快,也避免正则写错或漏边界(比如邮箱中 + 号合法但常被正则误杀) - 出错时用
input.validationMessage获取浏览器默认提示文本,比自己拼字符串更一致 - 注意:Safari 对某些
type(如date)的validity支持不全,需降级检查value.length或用pattern属性兜底
错误信息要绑定到具体 input,别只塞进一个 div
把所有报错都堆在表单顶部一个 <div id="error-summary"> 里,用户得来回滚动找问题在哪。真正有效的错误反馈,必须和对应字段强关联。
<ul>
<li>每个 <code><input> 后紧跟一个 <span class="error" data-for="email"></span>,JS 校验失败时往对应 span 填内容
aria-invalid="true" 和 aria-describedby 属性让屏幕阅读器可读,例如:<input aria-invalid="false" aria-describedby="email-error"><span id="email-error"></span>
aria-hidden 或移除元素内容不可靠,应直接操作 textContent 和 aria-invalid
后端返回的错误字段名要和前端 name 属性对齐
前后端字段名不一致是最隐蔽的修复失败原因。比如后端返回 {"user_email": "格式错误"},但前端 input 的 name="email",JS 就找不到匹配项,错误永远显示不出来。
立即学习“前端免费学习笔记(深入)”;
- 统一约定:前后端使用完全相同的字段标识符,推荐小写字母+下划线(
phone_number)或驼峰(phoneNumber),但必须全程一致 - 后端返回的错误结构建议固定为:
{"field_errors": {"email": ["请输入有效邮箱"], "password": ["至少8位"]}},前端遍历field_errors键即可映射 - 如果无法改后端,前端做一次字段映射表,但别硬编码在验证函数里——放在配置对象中,方便后续调整
表单错误修复不是“加上提示就行”,关键在事件拦截是否彻底、验证依据是否可信、反馈路径是否精准、前后端契约是否清晰。少一个环节,用户就会卡在某个看不见的断点上。











