表单内嵌Accordion自动提交问题及示例代码
解决表单内Accordion点击触发表单提交的问题
我刚搞定这个问题,特意分享出来帮其他开发者避坑!
问题场景
页面表单里放了几个Accordion组件,本来是让用户折叠已经浏览过的内容,结果按常规写法实现后,一点击展开Accordion,表单就自动提交了,完全不符合预期。
问题根源
问题出在<button>元素的默认行为上——在<form>标签内部的按钮,默认的type属性是submit,所以每次点击Accordion的按钮,浏览器都会把它当成表单提交按钮来处理,直接触发了表单提交,而不是只执行我们写的折叠逻辑。
两种简单解决方案
方案1:给Accordion按钮添加type="button"
直接给所有带accordion类的按钮加上type="button",明确告诉浏览器这是一个普通功能按钮,不是提交按钮,从根源上避免误触发:
<!DOCTYPE html> <html> <head> <style> .accordion { background-color: #eee; color: #444; cursor: pointer; padding: 18px; width: 100%; border: none; text-align: left; outline: none; font-size: 15px; transition: 0.4s; } .active, .accordion:hover { background-color: #ccc; } .panel { padding: 0 18px; display: none; background-color: white; overflow: hidden; } </style> </head> <body> <h2>Accordion</h2> <form action="fail" method="post" enctype="multipart/form-data"> <button class="accordion" type="button">Section 1</button> <div class="panel"> <input type="checkbox" name="checkbox1.1">Checkbox 1.1 <br> <input type="checkbox" name="checkbox1.2">Checkbox 1.2 </div> <button class="accordion" type="button">Section 2</button> <div class="panel"> <input type="checkbox" name="checkbox2.1">Checkbox 1.1 <br> <input type="checkbox" name="checkbox2.2">Checkbox 1.2 </div> <input type="submit" value="Submit"> </form> <script> var acc = document.getElementsByClassName("accordion"); var i; for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { this.classList.toggle("active"); var panel = this.nextElementSibling; if (panel.style.display === "block") { panel.style.display = "none"; } else { panel.style.display = "block"; } }); } </script> </body> </html>
方案2:在点击事件中阻止默认行为
如果不想修改HTML结构,也可以在JavaScript的点击事件里添加event.preventDefault(),手动阻止按钮的默认提交行为:
for (i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function(event) { // 阻止表单提交的默认行为 event.preventDefault(); this.classList.toggle("active"); var panel = this.nextElementSibling; if (panel.style.display === "block") { panel.style.display = "none"; } else { panel.style.display = "block"; } }); }
两种方案都能解决问题,个人更推荐第一种,从HTML层面就明确按钮的用途,逻辑更清晰也更易维护。
内容的提问来源于stack exchange,提问作者Amos Baker
相关产品推荐
相关产品推荐

