一个搜索框,回车就刷新页面。表单标签上写了 onsubmit 等于 return false,还是刷。

这种写法在行内属性里是有效的,问题往往出在别处:要么函数没返回值,要么事件是 addEventListener 绑的。

return false 到底做了什么

在 HTML 属性和老式 onclick 绑定里,返回 false 等于同时做两件事:阻止默认行为,阻止事件冒泡。所以它看起来特别好用。

用 addEventListener 绑的回调,返回值会被忽略。想拦默认行为,得显式调用 preventDefault。这是从 jQuery 转原生时最容易踩的坑。

三种拦住的方式,别混用

preventDefault 只拦默认行为,不拦冒泡。stopPropagation 只拦冒泡,不拦默认行为。return false 两个都拦。先想清楚要拦哪个,再选方法。

按钮是 submit 类型时,点它等于提交表单。只想做校验不想提交,把按钮改成 button 类型,或者干脆不用 form。

两个都调用也行,顺序别反。先 preventDefault,再 stopPropagation,否则外层容器可能先收到事件。

几个具体场景

  • 校验不通过还提交:函数里只写了 return,没有返回 false。
  • jQuery 的 on 里 return false 有效,addEventListener 里无效,两套规则。
  • 异步校验:请求还没回来,提交已经走了,得先拦住再手动提交。
  • React 的 onSubmit 里用 preventDefault,别指望 return false。

还有一种情况:表单上有多个 submit 按钮,代码只拦了其中一个。点另一个照样提交,看起来就像拦截失效。

调试顺序

在回调第一行打日志,确认进没进。进了还不拦,就是 preventDefault 没写,或者写在了异步回调后面。没进,说明别处也绑了 submit,或者表单被脚本直接提交了。

一句话:老式绑定看返回值,现代绑定看 preventDefault。混着用,问题就藏起来了。