必须调用 e.preventDefault(),否则表单仍会按原生逻辑提交并刷新页面;checkValidity()仅返回布尔值判断校验状态,不阻止提交行为,漏掉 preventDefault()会导致验证通过后仍刷新。

必须调用 e.preventDefault(),否则表单仍会按原生逻辑提交并刷新页面——验证通过只是浏览器放行了校验,不代表你放弃了控制权。
为什么 checkValidity() 返回 true 还会刷新
浏览器的 checkValidity() 只判断字段是否满足 required、type="email" 等约束,并不阻止提交行为。只要没显式调用 e.preventDefault(),表单就会走默认流程:发送请求、跳转或刷新。
- 常见错误:只写
if (form.checkValidity()) { /* 发送 AJAX */ },漏掉e.preventDefault() - 更隐蔽的坑:在按钮
click事件里做校验并调用form.submit()——这会绕过所有 submit 监听器,直接触发原生提交 - Bootstrap 5 的
.was-validated类只影响样式,和是否阻止提交完全无关
submit 事件监听必须绑定到 <form></form> 元素上
不能只监听按钮的 click,否则无法捕获回车提交、form.submit() 调用等其他触发方式,且原生验证(如 required 提示)也不会自动弹出。
- 正确写法:
document.getElementById('myForm').addEventListener('submit', function(e) { e.preventDefault(); ... }) - 如果表单是动态插入的(比如从 API 加载后 append 到 DOM),要用事件委托:
document.addEventListener('submit', function(e) { if (e.target.matches('#myForm')) { e.preventDefault(); ... } }) - 用 jQuery 时注意:不要写成
$('button[type="submit"]').on('click', ...),这是错的路径
AJAX 提交后要不要手动 reset() 表单
要,但得看场景。验证成功后执行 AJAX,响应成功再重置,能避免用户重复点击;但如果表单含文件上传或富文本编辑器,reset() 会清空它们的内部状态,反而出问题。
- 普通文本/选择框:可安全调用
form.reset() - 含
<input type="file">:改用 JS 逐个清空值,例如input.value = '',避免触发浏览器的“拒绝访问”保护 - 用了第三方编辑器(如 TinyMCE):必须调用其 API 清空,不能依赖
form.reset() - 模态框场景下,常需在 AJAX 成功后调用
bootstrap.Modal.getInstance(modalEl).hide(),而不是只 reset 表单
最容易被忽略的是:即使你用 fetch 或 axios 发了请求,只要没在 submit 事件里调用 e.preventDefault(),浏览器就已在后台发起了一次原生 POST,导致双提交、CSRF 失败或服务端报错。这个动作不是“可选优化”,而是前提条件。


















