不写 type 的 <button> 在 <form> 内默认为 submit——所有现代浏览器和 W3C 规范均明确此行为;它触发 submit 事件导致表单提交与页面刷新,须在 <form> 上监听 submit 并 preventDefault 才能阻止;非提交按钮必须显式写 type="button"。

不写 type 的 <button> 在 <form> 内部默认是 submit,不是 button——这是所有现代浏览器(Chrome、Firefox、Safari、Edge)和 W3C 规范一致的行为,不是兼容性问题,而是明确的默认语义。
为什么点一下按钮就刷新页面?
只要 <button> 出现在 <form> 标签内,且没写 type 属性,浏览器就会把它当 type="submit" 处理。它会立即触发原生 submit 事件,走完整表单提交链路:收集 name 字段 → 构造请求 → 发送到 action 地址 → 页面刷新(哪怕 action 为空或没写)。
常见现象包括:
- JS 的
onclick或框架的@click/onClick执行了,但紧接着页面跳转/白屏 - Network 面板出现一次空 POST/GET 请求,URL 是当前页
- React/Vue 中状态更新被中断,控制台看不到报错,只看到上下文丢失
type="submit" 和 type="button" 的行为边界在哪?
二者不是“能不能绑 click”的区别,而是是否参与表单生命周期的根本差异:
立即学习“前端免费学习笔记(深入)”;
-
type="submit"触发的是submit事件,不是click;仅监听按钮的click并调用preventDefault()拦不住提交 - 想真正阻止提交,必须在
<form>上监听submit事件,并调用event.preventDefault() -
type="button"完全静默,不触发任何表单行为,也不冒泡到form的submit,只响应你手动绑定的click -
type="reset"不是“清空”,它只把每个字段的value设回 HTML 加载时的初始值(即<input value="abc">中的"abc"),JS 后续设的值、动态插入的字段、defaultValue都不生效
非法 type 值或空字符串会怎样?
浏览器只认 submit、reset、button 这三个合法值。其他任何值(比如 type="primary"、type=""、type="click")都会降级处理:
- 在
<form>内部 → 当作submit - 在
<form>外部 → 当作button
这种降级不可靠,且掩盖了语义错误。更危险的是:模板引擎(EJS/Nunjucks)、低代码平台、甚至某些 SSR 工具生成的按钮,可能默认不注入 type,上线后才暴露问题。
React/Vue 中要不要写 type="button"?
要,而且必须显式写。框架不会帮你补这个属性:
- JSX 写
<button onClick={handleCancel}>取消</button>,如果组件最终渲染在<form>内,DOM 中就是type="submit" -
@click.prevent或onClick={(e) => e.preventDefault()}是兜底手段,但不该是第一道防线 - 真正稳定的做法是:所有非提交意图的按钮,一律写
<button type="button">,哪怕它当前不在<form>里——重构时移进表单,也不会埋雷
最常被忽略的点是嵌套层级:按钮可能不在直接子级,但在祖辈 <form> 内,照样继承默认 submit 行为。语义先行,比 JS 拦截更底层、更可靠。



















