确定事件是否在外部委托调用中是defaultPrevented

时间:2015-02-12 17:32:24

标签: jquery javascript-events

给定两个jQuery函数直接绑定到一个元素并通过委托。

$("a").on("click", function (e) {
    console.log(e.isDefaultPrevented()); // returns false.
    // TODO: Determine whether the other function isDefaultPrevented.
});

$("body").on("click", "a", function (e) {
    e.preventDefault();
    console.log("I am a delegated call");
});

如何在直接绑定函数中确定是否已在委派函数中调用e.preventDefault();

理论上我可以遍历DOM并使用$._data()检查任何绑定的事件处理程序,并使用/preventDefault\(\)/.test(handler)将该函数解析为字符串,但这将是非常不明智的,因为它既昂贵又{ {1}}也标记为折旧,支持私有$._data()变量。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

  

如何在直接绑定函数中确定是否已在委派函数中调用e.preventDefault();

不能,因为尚未调用委托功能。您的直接处理程序将始终在与同一元素匹配的委托处理程序之前调用,因为委托处理程序在事件冒泡之前不会运行,这是在直接处理程序已经执行之后

如果您可以控制两个处理程序,那么您当然可以在它们之间建立通信:

(function() {
    $("a").on("click", function (e) {
        var $this = $(this);

        // Direct handler is always called first
        $this.data("prevented", false);
        setTimeout(function() {
            if ($this.data("prevented")) {
                // Prevented by delegated handler
            }
        }, 0);
    });

    $("body").on("click", "a", function (e) {
        e.preventDefault();
        $(this).data("prevent", true);
    });
})();

但当然,到那个时候,如果你想要在直接处理程序中阻止它,为时已晚。

示例:

$("#container div").on("click", function(e) {
  snippet.log("direct called");
  var $this = $(this);
  $this.data("prevent", false);
  setTimeout(function() {
    if ($this.data("prevent")) {
      snippet.log("direct detected default prevented");
    } else {
      snippet.log("direct detected default NOT prevented");
    }
  }, 0);
});
$("#container").on("click", "div", function(e) {
  var $this = $(this);
  snippet.log("delegated called");
  if ($this.hasClass("prevent")) {
    e.preventDefault();
    $this.data("prevent", true);
    snippet.log("delegated prevented default");
  }
});
<div id="container">
  <div class="prevent">
    Click me and the delegated handler will prevent the default.
  </div>
  <div>
    Click me and the delegated handler <strong>won't</strong>
    prevent the default.
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

如果你不这样做,那就让它变得更加棘手。你可以使用setTimeout等待委托处理程序运行后检查,但是你必须检查e.originalEvent,而不仅仅是e,这会带来跨浏览器问题:< / p>

$("a").on("click", function (e) {
    setTimeout(function() {
        if (e.originalEvent.isDefaultPrevented()) {
            // Yes, the delegated handler prevented it
        }
    }, 0);
});

...因为委托处理程序中的e对象与直接处理程序中的e对象不同; jQuery创建单独的(使用相同的底层原始事件)。

当然,您可以解决这些跨浏览器问题;检查e.originalEvent.isDefaultPrevented并在那里使用它,如果没有查看e.originalEvent.returnValue(IE特定的东西)......

如果你需要的话,在直接处理程序中阻止它仍然是迟到的。

示例:

$("#container div").on("click", function(e) {
  snippet.log("direct called");
  setTimeout(function() {
    // Cross-browser issue here
    if (e.originalEvent.isDefaultPrevented()) {
      snippet.log("direct detected default prevented");
    } else {
      snippet.log("direct detected default NOT prevented");
    }
  }, 0);
});
$("#container").on("click", "div", function(e) {
  snippet.log("delegated called");
  if ($(this).hasClass("prevent")) {
    e.preventDefault();
    snippet.log("delegated prevented default");
  }
});
<div id="container">
  <div class="prevent">
    Click me and the delegated handler will prevent the default.
  </div>
  <div>
    Click me and the delegated handler <strong>won't</strong>
    prevent the default.
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>