我有一个输入表单,带有一个提交按钮。我不希望用户能够双击提交按钮并再次提交表单...
因此,我已在表单中添加了以下jQuery:
var prevSubmitTime = new Date('2000-01-01');
function preventFromBeingDoubleSubmitted() {
$('form').each(function () {
$(this).submit(function (e) {
if ($("form").valid()) {
var curSubmitTime = new Date($.now());
// prevent the second submit if it is within 2 seconds of the first submit
if (curSubmitTime - prevSubmitTime < 2000) {
e.preventDefault();
}
prevSubmitTime = new Date($.now());
}
});
});
}
$(document).ready(function () {
preventFromBeingDoubleSubmitted();
});
上面的代码存储了提交时间,并阻止了第二次提交,如果为时过早(少于2秒),我不希望永久禁用提交按钮,以防服务器端出现错误。
此代码可以满足我的要求,但是在调试代码时,即使双击提交按钮,我也永远无法触及e.preventDefault();
的断点。
似乎第二个提交事件正在等待第一个提交事件完成,然后再触发。
但是,如果我删除了preventFromBeingDoubleSubmitted()
函数,则可以通过双击“提交”按钮来两次提交表单。
任何人都可以解释为什么有时有时一次又一次触发提交事件...有时不是这种情况吗?将事件处理程序放入.each()
内是否会影响其执行行为?
答案 0 :(得分:4)
在您的代码段中,我添加了一些可能有用的日志。当您提出多个问题时,我将一一回答。
var prevSubmitTime = new Date('2000-01-01');
function preventFromBeingDoubleSubmitted() {
$('form').each(function () {
$(this).submit(function (e) {
console.log('I am going to submit form');
if ($("form").valid()) {
var curSubmitTime = new Date($.now());
console.log('I am a valid form')
// prevent the second submit if it is within 2 seconds of the first submit
if (curSubmitTime - prevSubmitTime < 2000) {
console.log('A small time difference. So I am stopping')
e.preventDefault();
}
prevSubmitTime = new Date($.now());
}
});
});
}
$(document).ready(function () {
preventFromBeingDoubleSubmitted();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.js"></script>
<form id="myform">
<input type="text" name="q" required="required" />
<br />
<input type="text" name="bar" required="required" />
<br />
<br />
<input type="submit" />
</form>
谁能解释为什么有时会触发提交事件 紧接着一个接一个...有时不是这样吗?
我认为您已经回答了这个问题。您正在添加代码,以检查第一次单击提交按钮与第二次单击之间的时间差。如果存在时差,则停止第二个表单提交。
我永远都无法在e.preventDefault()上达到断点;
无法获得控制台的原因是,当您单击“提交”按钮时,您正在重定向离开该页面。这样便清除了控制台。如果要查看控制台,请使用ajax函数提交表单。返回时,您可能可以将页面重定向到某个地方。
是否将事件处理程序放入.each()中,影响其执行 行为?
不。它只是一个迭代器。不会影响提交功能。
我已经添加了一个指向jsfiddle的链接。在preventDefault之前添加警报将阻止页面暂时重定向。这将证明执行已发生。
答案 1 :(得分:4)
默认情况下提交表单时,导航到设置的action
网址。在未明确设置的情况下,URL为当前页面。第一个提交呼叫将最终开始导航过程。在此期间,当前已加载的javascript代码将被卸载。这包括事件处理程序。因此,为什么会出现双重提交或不一致的矛盾。如果网络请求和其他页面处理操作URL发生的速度比您再次单击事件处理程序的速度要快,则不会再调用/到达您的断点,因为它们已被卸载。反之亦然,如果网络请求较慢,则可以使处理程序被调用并到达断点(如果尚未卸载)。
您说您不想永久禁用“提交”按钮,但是即使您将其禁用,表单提交也将导致页面更改,在您的示例中,这只会使用新的提交加载同一页面按钮,因为它有一个新页面,所以将不再被禁用。因此,从一开始它就永远不会真正消失。
现在,如果您的真实表单实际上未进行正常的表单提交,并且您正在使用ajax请求,Web套接字连接等功能,则可以在按钮之前将按钮设置为Disabled(或设置busy标志)请求并在ajax请求回调,Web套接字事件等中取消设置。
例如:
jQuery('form').on('submit',function(e){
e.preventDefault();
var fd = new FormData(this);
jQuery('yourbutton').prop('disabled',true);
fetch('url',{method:"post",body:fd}).then(()=>jQuery('yourbutton').prop('disabled',false));
});
答案 2 :(得分:1)
您的解决方案过于复杂。防止重复提交的最简单方法是禁用提交按钮。
示例:
var submittable = false;
$('form').submit(function (e) {
if (!submittable) {
e.preventDefault();
var $this = $(this);
var $submitButton = $this.find('button[type="submit"]');
$submitButton.attr('disabled', true);
if (CONDITION_SATISFIED) {
submittable = true;
$this.submit()
} else {
$submitButton.attr('disabled', false);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<button type="submit">Submit</button>
</form>
答案 3 :(得分:1)
如果在进行e.preventDefault();
之前添加$("form").valid()
,将会看到抛出错误。
script.js:7 Uncaught TypeError: $(...).valid is not a function
at HTMLFormElement.<anonymous> (script.js:7)
at HTMLFormElement.dispatch (jquery.min.js:2)
at HTMLFormElement.y.handle (jquery.min.js:2)
首先看不到此错误,因为如果未执行任何其他操作,提交者实际上会更改页面(在这种情况下刷新页面)。
但是,通常,惯例是在提交表单后导航到另一个页面。 如果您仍然希望采用这种方法并限制提交的次数,建议将 submitted 状态保留在局部变量中,并根据服务器端的验证进行更改。
最后一件事..我不理解通过表单进行的迭代,因为您的HTML中只有一个-> $('form').each
是没有用的。
答案 4 :(得分:0)
我知道您想要什么,但是您使它变得非常复杂。无需插入提交按钮,只需添加一个简单的div
并在其上添加一个点击处理程序即可。
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="myform">
<input type="text" name="myInput" />
<div id="submit" onclick="myform_submit()" />
</form>
和:
function myform_submit() {
if ($('#submit').hasClass('busy')) { return; }
$('#submit').addClass('busy');
// do the tasks then remove the `busy` class :
$('#submit').removeClass('busy');
}
我只是展示这个想法,您可以做得更好。