blogWithMarkdown icon indicating copy to clipboard operation
blogWithMarkdown copied to clipboard

button不只是button

Open spacewander opened this issue 9 years ago • 3 comments

今天写前端页面的时候发现了一个有趣的事情,或者说bug吧。点击一个按钮,会导致页面跳转到404。查了下浏览器请求,发现是一个POST请求导致的。这个页面包含了一个form,确实是想让它POST数据给后台。不过按照设定,应该是通过AJAX实现的,而不是直接重新加载页面。

看来不知道是什么触发了表单的submit事件。仔细阅读下相关的代码,这个按钮被按下时,会去检查表单是否正确,如果正确,则通过AJAX去进行POST。注意,这个按钮只是普通的<button>,并不是<input type="submit">。然而在页面跳转的同时,检查表单正确性部分的代码也不能工作了。

因为浏览器在POST之后会重新加载内容,不会保留之前的log,这给调试带来了麻烦。花了我不少时间,终于把bug揪出来了。原来是某一个分支中,event.preventDefault()被绕过了,导致原来的事件没有拦住。一开始发现这一点时,我是感到很奇怪的,原来的事件不只是click么?怎么会是submit呢?

查了下,原来button元素默认是type="submit",也即在form中,点击button自然会触发submit事件。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <form action="/test" method="post">
    <button>don't submit</button>
  </form>
</body>
</html>

即使这个button已经标明是“don't submit”了,呵呵。 解决之道很简单,就是指定type="button",这样它就是人畜无害、天真无邪的好button了。

如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <form action="/test" method="post">
    <button>submit</button>
    <button type="button">don't submit</button>
  </form>
  <button>just click it</button>
</body>
</html>

如果这个buttonform之外,那么就不会触发submit事件。然而在html5标准中,你可以通过设置form="#form_id"属性来给button指定一个非直系祖先的form

这篇debug小文本来打算发到SegmentFault上的,不过考虑到它实在太短,干货还不够多,所以就放到这里了。

spacewander avatar May 17 '15 16:05 spacewander

cool! Thanks a lot!

parabolazz avatar Nov 08 '16 11:11 parabolazz

牛逼,我今天也碰到了,写在form中完全是为了方便布局好看,我还以为是其他的js库把form里面的button的click事件给拦截了,按照你说的的确解决了问题

sjq597 avatar Mar 27 '17 13:03 sjq597

这个很好,非常感谢解决了我的问题,按钮在form里面,本来是设置了ajax的post方法,点击直接提交本页面了,一直失败,原来是属性的问题,十分感谢!!

EthanLLL avatar Nov 07 '17 16:11 EthanLLL