点击按钮延迟2秒提交表单,如何携带按钮name/value参数?
问题
点击带有name/value对的按钮后,延迟2秒提交表单,要求按钮的name/value作为表单数据的一部分提交。无JavaScript时表单可直接提交并携带参数,但当前用jQuery实现的代码延迟提交后,URL仅显示?,choice参数未被携带。
最小可复现代码
<!doctype html> <html lang="en"> <head> <script src="import/jquery-3.6.4.min.js"></script> <script> $(document).ready(function(){ var waittime=2; var blocksubmit=true; $('form').submit(function (evt) { if (blocksubmit) evt.preventDefault(); }); $('button').click(function(me){ theval = this.value; $('#msg').html('Submitting "'+theval+'" in '+waittime+' seconds.'); setTimeout( function () { blocksubmit=false; $('form').first().trigger('submit'); $('#msg').html('The URL should now display ?'+theval+' at its end.'); }, 1000*waittime ); }); }); </script> </head> <body> <form action="?" method="get"> <p id="msg">Choose one:</p> <button name="choice" value="True">True</button> <button name="choice" value="False">False</button> </form> <p>Expected behavior: Two seconds after clicking a button, the browser loads `?choice=True` or `?choice=False`.</p> <p>Actual behavior: Two seconds after clicking a button, the browser loads `?`. The input value is not included.</p> </body> </html>
核心疑问:为何点击按钮设置的表单数据被忽略,提交时choice参数未被携带?
问题原因
这是因为手动触发表单提交和用户点击按钮提交的逻辑存在本质差异:
- 点击按钮时,浏览器原本会记录「该按钮是提交触发源」,自动把它的
name/value加入提交数据,但你的代码没有阻止按钮的默认提交行为,导致表单先触发了一次提交——又被blocksubmit=true的逻辑用preventDefault()拦截,这次拦截直接让浏览器丢失了「哪个按钮触发提交」的上下文。 - 2秒后通过
$('form').trigger('submit')手动触发提交时,这是一个无触发源的提交,浏览器不知道是哪个按钮发起的操作,自然不会把任何按钮的参数添加到表单数据中。
简单总结:用户点击按钮提交,浏览器会绑定触发源并携带其参数;代码调用submit()方法提交,没有触发源,就不会带按钮参数。
解决方案
方案1:用隐藏输入框保存按钮值(通用可靠)
在表单内新增一个隐藏的<input>,点击按钮时将按钮的value赋值给它,这样无论哪种方式提交表单,参数都会被携带:
<form action="?" method="get"> <p id="msg">Choose one:</p> <!-- 新增隐藏输入框,用于存储选中的按钮值 --> <input type="hidden" name="choice" id="hidden-choice"> <button name="choice" value="True">True</button> <button name="choice" value="False">False</button> </form>
修改JavaScript代码:
$('button').click(function(evt){ // 阻止按钮默认提交行为,避免触发无效的表单提交 evt.preventDefault(); var selectedVal = this.value; // 将选中的按钮值赋值给隐藏输入框 $('#hidden-choice').val(selectedVal); $('#msg').html('Submitting "'+selectedVal+'" in '+waittime+' seconds.'); setTimeout(function () { blocksubmit = false; $('form').first().submit(); $('#msg').html('The URL should now display ?'+selectedVal+' at its end.'); }, 1000*waittime); });
方案2:直接修改表单action(仅适用于GET方法)
由于你的表单使用GET方法,也可以在点击按钮时直接将参数拼接到表单的action属性中:
$('button').click(function(evt){ evt.preventDefault(); var selectedVal = this.value; $('#msg').html('Submitting "'+selectedVal+'" in '+waittime+' seconds.'); setTimeout(function () { // 修改表单action属性,直接带上参数 $('form').first().attr('action', '?choice=' + selectedVal).submit(); $('#msg').html('The URL should now display ?'+selectedVal+' at its end.'); }, 1000*waittime); });
注意:该方法仅适用于GET类型表单,如果是POST表单则不适用,方案1的通用性更强。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

