1

我的目标是防止所有点击事件(点击时隐藏/显示 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 实现我的目标?

谢谢!

4

1 回答 1

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

    为此(防止进一步传播并防止当前元素上的任何进一步事件处理程序被触发),您需要调用(相反,不要调用)。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");
      }));
      

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

于 2013-05-20T22:48:08.647 回答