【问题标题】:Can JavaScript or jQuery detect when event propagation is complete?JavaScript 或 jQuery 能否检测到事件传播何时完成?
【发布时间】:2014-11-15 17:44:34
【问题描述】:

在 JavaScript 或 jQuery 中有什么方法可以检测事件何时完成向 DOM 传播?我有一个 jQuery 点击处理程序,它在点击时附加(带有目标“htm​​l”),并且一旦它冒泡到目标,添加它的点击就会触发它。我想延迟处理程序附件,直到传播完成。我听说 event.stopPropagation() 是有风险的业务,所以我宁愿不使用它。

这是我的代码。 #title-editable 是一个锚标记。 vclick 是由 jQuery Mobile 定义的事件。我只需单击#title-editable 即可获得两个控制台日志。

  $("#title-editable").on("vclick", function(event){
    event.preventDefault();
    console.log("First handler fired.");
    /* Would like to detect completion of event propagation here 
      and only execute the next statement after that. */
    $("html").one("vclick",function(){
      console.log("Second handler fired.");
    });
  });

编辑:我想我有一个解决方法。而不是 .one 用于内部事件,我使用 .on 因此事件在第一次触发时不会分离。我检查点击事件的目标,只对内部事件执行更改,如果目标不是#title-editable,则分离内部事件。

  $("#title-editable").on("vclick", function(event){
    event.preventDefault();
    console.log("First handler fired.");
    $("html").on("vclick",function(event2){
      console.log("Second handler fired.");
      if(!$(event2.target).closest("#title-editable").length){
        console.log("Execute changes here.");
        $("html").off("vclick");
      }
    });

【问题讨论】:

  • 这毫无意义?这很可能是 X/Y 问题,如果有人能理解的话?
  • 通常body 是事件冒泡的目的地。但是如果你在那里处理事件,如果某些代码在树下某处调用stopPropagation() 怎么办?
  • 你能指出什么没有意义吗?我正在尝试做的基本事情是在单击#title-editable 时将单击事件附加到文档,但不会触发。有没有更好的方法来做到这一点?
  • 这是我想要的行为。用户点击#title-editable。发生了一些变化。 (具体来说,我在#title-editable 的祖先上设置了一个类,#title-editable 以 display:none 消失,并出现一个输入元素。)如果用户随后单击其他任何地方,则会发生相反的变化。
  • 这是一个 jQuery 错误。在原生 DOM 中,调度期间安装的处理程序不会触发。

标签: javascript jquery events propagation


【解决方案1】:

根据您最后的评论,最简单的逻辑是这样的:

var changed=false;
$('#title-editable').on('vclick',function(event){
    event.preventDefault();
    console.log("First handler fired.");
    changed=true;
});
$(document).on("vclick",function(){
    if(changed){
        console.log("Second handler fired.");
        //here you can revert your actions and then the next line
        changed=false;
    }
});

更新:

第二个理论:

您说祖先在点击#title-editable 时会获得一个类,因此您可以尝试以下代码:

$(document).on("vclick",function(event){
    if($('#title-editable').parent().hasClass('givenClass')){ //assuming the class is called "givenClass" and the ancestor is the parent of "#title-editable" (you need to sort that out)
        console.log("Second handler fired.");
        //here you can revert your actions and then the next line
    }
    else{
        event.preventDefault();
        console.log("First handler fired.");
    }
});

第三种理论:

$(document).on("vclick",function(event){
    if(!$('#title-editable').is(':visible')){
        console.log("Second handler fired.");
        //here you can revert your actions and then the next line
    }
    else{
        event.preventDefault();
        console.log("First handler fired.");
    }
});

第四理论:

$(document).on("vclick",function(event){
    if(!$('#title-editable').is(event.target) || !$('#title-editable').has(event.target)){
        console.log("Second handler fired.");
        //here you can revert your actions and then the next line
    }
    else{
        event.preventDefault();
        console.log("First handler fired.");
    }
});

【讨论】:

  • 感谢您的建议,但似乎有同样的问题。我试了一下,两个控制台日志再次单击即可触发。我认为发生的事情是 changed=true;在事件冒泡到文档根之前执行。
  • 第二个理论似乎也有同样的问题——类添加和类检查的时间反映了第一个理论中布尔变量的时间。
  • 我认为第三个理论也是如此。 #title-editable 在被点击后变得不可见,这似乎在点击事件到达文档之前被执行。所以“如果”总是评估为真。
  • 我想出了一个似乎可以做到的解决方法。将其添加到原始问题中。感谢您尝试帮助我!
  • 不客气,很高兴你得到了答案,但以防万一尝试我刚刚添加的第四个理论,我认为它也会起作用!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多