点按钮刷新页面是因为button在form内未设type属性时默认为submit,触发表单提交;必须监听form的submit事件并调用e.preventdefault()阻止,默认行为无法通过click事件完全拦截。

为什么点按钮会刷新页面
因为 <button></button> 在 <form></form> 里没写 type 属性时,默认就是 type="submit"。只要它存在,点击或回车都会触发表单提交——浏览器不管你的 JavaScript 有没有绑事件、有没有发请求,它只认这个默认行为。
常见错误现象:
- 控制台刚打印出
"正在提交...",页面就闪一下刷没了 - fetch 请求发了一半,页面跳走,Promise 永远不会 resolve
- 用
onclick="return false"写在按钮上,回车仍刷新(因为回车不触发 click)
阻止刷新必须监听 form 的 submit 事件
只监听按钮 click 是拦不住的:回车、JS 调用 form.submit()、甚至某些移动端软键盘“发送”键,都绕过 click,直奔 submit 事件而去。
正确做法是统一收口:
- 给
<form></form>绑submit事件 - 第一行必须写
e.preventDefault(),不能加条件判断,不能异步延迟 - 不要在按钮
click里调form.submit(),这会跳过submit监听器
示例:
form.addEventListener('submit', e => {
e.preventDefault(); // 必须放最前
fetch('/api', { method: 'POST', body: new FormData(form) });
});
button type 不写等于埋雷
动态插入的按钮、模板渲染出来的按钮、甚至复制粘贴的代码,只要漏了 type="button",放进 <form></form> 就自动变成提交按钮。
容易被忽略的细节:
-
<input type="button">安全,但语义弱;<button type="button"></button>更推荐 - Vue/React 渲染时,别依赖 props 默认值,显式传
type="button" - 用 Linter(如 ESLint)配规则
jsx-a11y/no-autofocus或自定义规则检查缺失type
textarea 回车换行和表单提交冲突怎么解
只有 <textarea></textarea> 需要特殊处理:用户按回车想换行,不是提交。其他输入框(input[type="text"])按回车就该提交,这是浏览器默认且合理的行为。
稳妥方案是监听 textarea 的 keydown,而不是拦整个表单:
- 只在
e.key === 'Enter'且无修饰键(!e.shiftKey)时e.preventDefault() - 手动插入
'\n'到光标位置(注意维护selectionStart) - 绝对不要对
input[type="text"]做同样操作,否则破坏基础体验
移动端软键盘的“回车”键映射不一致,iOS 和 Android 行为不同,实测比理论更重要。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











