在下面的代码中(JSFiddle在这里(:
<form>
<button>ok</button>
</form>
$(function(){
$('form').submit(false) ;
$('button').click(function(){ $('form').remove() }) ;
}) ;
当您在谷歌浏览器 48 中单击该按钮时,它会触发表单提交。
但是,如果您在 Firefox 43 中执行此操作,则不会提交表单。
在我看来,Firefox 的行为应该是正确的,但由于我对标准没有如此深入的了解,所以我真的不知道。
是行为错误还是有问题?
跟进:
我刚刚发现相同的测试用例但没有使用 jQuery 不会在两个浏览器中触发表单提交。
<form onsubmit="return false">
<button onclick="form.remove()">ok</button>
</form>
这可能是一个计时问题,因为Javascript中没有线程并发性。事件线程将始终按顺序运行,因此button
事件处理程序必须在form
事件处理程序启动之前完成。
我在这里瞎了眼。jQuery一定在Chrome中做了一些奇怪的繁琐事情。
跟进2:
这不是jQuery的问题。在jQuery错误跟踪器中,我被告知内联事件处理程序不遵循与addEventListener
附加的相同的规范,因此真正的功能等效代码应该是这样的:
<form>
<button>ok</button>
</form>
<script>
document.querySelector('form').addEventListener('submit',function(){ return false }) ;
document.querySelector('button').addEventListener('click',function(evt){ evt.target.form.remove() }) ;
</script>
这确实像jQuery版本一样。
您的第一个代码添加了一个 returnFalse
jQuery 事件侦听器:
$('form').submit(false);
在 jQuery 事件侦听器中,return false
等效于
event.stopPropagation();
event.preventDefault();
后者应阻止提交表格。
但是,在触发 submit
事件之前,请使用 $.fn.remove
。这不仅会从文档中删除表单,还会清理其 jQuery 数据,包括事件侦听器。
因此,当浏览器向窗体触发 submit
事件时,不会取消该事件。
然后浏览器的行为有所不同(演示(:
- 火狐浏览器不会提交已删除的表单
- Chrome 不在乎表单是否已被删除,无论如何都会提交
如果你不想删除jQuery数据,你应该使用vanilla-js方法而不是$.fn.remove
删除表单。
在第二个代码中,在 vanilla-js 事件处理程序中取消事件。
由于它不是 jQuery 数据,$.fn.remove
不会删除它,因此取消submit
事件并且不会提交表单。
在第三个代码中,使用vanilla-js方法删除表单,因此不会清理其jQuery数据。
这无关紧要,因为submit
事件侦听器也添加了 vanilla-js。
但是,该事件不会取消。这是因为,与 vanilla-js 事件处理程序和 jQuery 事件侦听器不同,vanilla-js 事件侦听器中返回的值被完全忽略。
因此,最后的结果与第一个代码相同,但它们并不等效。
如果要使用 vanilla-js 事件侦听器取消事件,则应使用
event.preventDefault();
这将使它的行为类似于第二个代码。
我认为它依赖于实现,不能保证相同的行为
当调用 $('form'(.remove(( 时,Chromium 和 Firefox 都不会调用由 $('form'(.submit(...( 安装的 form.onsubmit 处理程序。因此,这意味着表单在Chromium和Firefox中调用onsubmit之前被检查为已销毁(或实际已销毁(。
我认为 Chromium 不会在按下按钮发出处理默认提交操作时检查标记为已销毁的表单。但是 Chromium 会检查 prevent默认标志,其中按钮的默认操作是表单提交。因此,可以在 $('form'(.remove(( 之前或之后添加 event.preventDefault((。
在相反的火狐中,忽略阻止按钮按下事件的默认值,并将控制权传递给form.onsubmit。
因此,这两个浏览器关于 preventDefault 和 onsubmit 的行为完全相反。
就表单被标记为已销毁时表单提交的事实而言,可以想象软件设计在通信完成后而不是之前实际删除对象。但在我看来,这是错误。需要知道开发人员的想法。他们是否知道它,是这个错误或功能。