在以下代码中(JSFiddle here):
<form>
<button>ok</button>
</form>
$(function(){
$('form').submit(false) ;
$('button').click(function(){ $('form').remove() }) ;
}) ;
当您点击Google Chrome 48中的按钮时,它会触发表单提交 但是,如果您在Firefox 43中执行此操作,则表示没有表单提交。
在我看来,Firefox的行为应该是正确的,但由于我对标准没有这么深入的了解,我真的不知道。
行为是错还是错?
跟进:
我刚刚发现相同的测试用例但不使用jQuery不会在两个浏览器中都没有触发表单提交。
<form onsubmit="return false">
<button onclick="form.remove()">ok</button>
</form>
这可能不是时间问题,因为Javascript中没有线程并发。事件线程将始终按顺序运行,因此button
事件处理程序必须在form
事件处理程序启动之前完成。
我在这里失明了。 jQuery必须在Chrome中做一些奇怪的麻烦事情。
跟进2:
这不是一个jQuery问题。在jQuery bug跟踪器中,我被告知内联事件处理程序不遵循与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版本相同。
答案 0 :(得分:0)
我认为这是依赖于实现的,而不是保证相同的行为
答案 1 :(得分:0)
Chromium和Firefox都没有调用$('form')安装的form.onsubmit处理程序。当$('form')。remove()调用时,提交(...)。因此,这意味着在Chromium和Firefox中调用onsubmit之前,将表单检查为已销毁(或实际销毁)。
我认为当按下按钮发出的处理默认提交操作时,Chromium不会检查标记为已销毁的表单。但是Chromium会检查preventDefault标志,其中按钮的默认操作是表单提交。因此可以在$('form')之前或之后添加event.preventDefault()。remove()。
在对面的Firefox中忽略按钮事件的preventDefault并将控制传递给form.onsubmit。
因此,这两个浏览器关于preventDefault和onsubmit的行为正好相反。
对于表单被标记为销毁时表单提交的事实,可以想象在通信完成之后实际删除了对象的软件设计而不是之前。但在我看来,这是错误。需要知道开发人员的想法。他们是否知道这个,是这个错误或功能。
答案 2 :(得分:0)
您的第一个代码添加了一个returnFalse
jQuery事件监听器:
$('form').submit(false);
在jQuery事件监听器中,return false
等同于
event.stopPropagation();
event.preventDefault();
后者应该阻止提交表单。
但是,在触发submit
事件之前,您使用$.fn.remove
。这不仅可以从文档中删除表单,还可以清除其jQuery数据,包括事件监听器。
因此,当浏览器将submit
事件触发到表单时,它不会被取消。
然后浏览器的行为方式不同(demo):
如果您不想删除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();
这会使它表现得像第二个代码。