在事件冒泡阶段删除祖先

问题描述 投票:3回答:3

在以下代码中(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版本。

javascript html dom-events dom-manipulation event-bubbling
3个回答
0
投票

您的第一个代码添加了一个returnFalse jQuery事件监听器:

$('form').submit(false);

在jQuery事件监听器中,return false等效于

event.stopPropagation();
event.preventDefault();

稍后应阻止提交表单。

但是,在触发submit事件之前,请使用$.fn.remove。这不仅从文档中删除了表单,还清理了它的jQuery数据,包括事件侦听器。

因此,当浏览器向表单触发submit事件时,不会取消它。

然后浏览器的行为有所不同(demo):

  • Firefox不提交已删除的表单
  • 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();

这将使其表现得像第二个代码。


0
投票

我认为这取决于实现,不能保证相同的行为


0
投票

Chromium和Firefox都不会调用$('form')。remove()时由$('form')。submit(...)安装的form.onsubmit处理程序。因此,这意味着在Chromium和Firefox中调用onsubmit之前,已将表单检查为已破坏(或确实已破坏)。

[我认为当按按钮发出的流程默认提交动作时,Chromium不会检查标记为已销毁的表单。但是Chromium会检查preventDefault标志,其中按钮的默认动作是表单提交。因此可以在$('form')。remove()之前或之后添加event.preventDefault()。

在相反的Firefox中,忽略按钮按下事件的preventDefault并将控件传递给form.onsubmit。

因此,这两个浏览器关于preventDefault和onsubmit的行为是完全相反的。

就将表单标记为已损坏时提交表单的事实而言,可以想象软件设计中的对象实际上是在通信完成之后而不是在此之前删除的。但在我看来,这是错误。需要知道开发人员的想法。他们是否知道这是错误或功能?

© www.soinside.com 2019 - 2024. All rights reserved.