【问题标题】:jQuery stopPropagation is ignoredjQuery stopPropagation 被忽略
【发布时间】:2013-05-20 22:21:19
【问题描述】:

我的目标是阻止所有点击事件(点击时隐藏/显示 HTML 中的元素),除非满足特定条件(用户在输入元素中有特定单词)。

所以我尝试将该逻辑添加到文档或“html”的点击处理程序中,但由于冒泡而首先触发了其他元素的点击处理程序。

所以我尝试将该逻辑附加到“*”,现在单击处理程序首先触发 - 但也将其传播到另一个元素,忽略 stopPropagation、preventDefault 并返回 false。

$(document).ready(function(){    
  $("*").click(function(event){
    if ($("#user").val() !== "admin"){
      console.log("1");
      event.stopPropagation();
      event.preventDefault();  
      return false;  
    }
  });
  $("#user").click(function(event){
    console.log("2");
    // do something
  });
});
  1. 当由于返回 false/stopPropagation 而不应进一步传播时,为什么在“1”之后将“2”写入控制台?
  2. 我还能如何使用 jQuery 实现我的目标?

谢谢!

【问题讨论】:

  • $("*").click我的心跳漏了一拍。
  • 如果你屏蔽了所有的点击事件,那么用户如何点击user元素才能进入admin
  • @Barmar,焦点从用户开始,我不会让它去其他任何地方
  • @yair:不要忘记标签功能。
  • 是的,我已经处理好了,谢谢 :)

标签: javascript jquery


【解决方案1】:
  1. stopPropagation() 防止事件在祖先树上进一步传播。但是,它不会阻止当前的剩余事件处理程序被触发。

    要做到this(防止进一步传播防止当前元素上的任何进一步事件处理程序被触发),您需要调用stopImmediatePropagation()(而不是也是)。

  2. 以这种方式将事件处理程序附加到每个元素,并调用stopImmediatePropagation()(以及preventDefault()阻止所有点击生效; 提供没有事件处理程序被绑定之前(因为处理程序是按顺序执行的;您不能撤消已经触发的处理程序)。

    这并不能使它很好,因为查找、枚举和将处理程序附加到每个元素都非常昂贵。

    为了使它更好,您的选择是:

    1. click 事件附加到document,只需preventDefault() 并牺牲stopImmediatePropagation()

    2. 在每个事件处理程序中检查#user 的状态;您可以通过滚动自己的包装函数来减轻这种痛苦;

      function checkUserState(then) {
          return function () {
              if ($("#user").val() !== "admin") {
                  then.apply(this, arguments);
              }
          };
      };
      

      ... 像这样使用;

      $("#user").click(checkUserState(function(event){
          console.log("2");
      }));
      

    正如 cmets 中所述,我有意避免使用事件委托的建议,因为虽然只允许附加一个事件处理程序而不是 n,但它不允许您附加 stopPropagation() 的事件。

【讨论】:

  • $(document).on("click", "*", ...) 将是实现这一点的更好方法,因为它不必为每个元素查找和绑定处理程序。
  • @Barmar: ...虽然你不会stopPropagation,因为事件已经冒泡到document
  • 谢谢!我不明白第一个更好的选项,我认为我们建立将点击处理程序附加到文档不会有帮助,因为它是最后触发的?
  • @yair:你是对的;它将最后被解雇。但是,这仍然可以让您preventDefault()(例如,阻止表单提交、链接打开等),只是来不及阻止其他事件处理程序触发(这就是我牺牲stopImmediatePropagation() 的意思)。这取决于该功能的重要性(防止事件处理程序触发,以及作为默认操作)。
  • 啊,我明白了,所以由于其他元素的操作是隐藏/显示/css 等。该选项不会执行,因为我需要处理程序来处理我试图阻止的其他操作。好的,非常感谢!我在这里学到了很多:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-19
  • 2019-09-11
  • 2013-02-11
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多