为什么总是在$(document).on(“ input propertychange”,“ .myClass”,function(){))之前调用$('。myClass')。on(“ input propertychange”,function(){})?

时间:2018-09-06 12:00:55

标签: jquery events

Here's一个工作示例:

$(document).on("input propertychange", ".myClass", function () {
    $('#result').append("first<br />");
});

$('.myClass').on("input propertychange", function () {
  $('#result').append("second<br />");
});

即使我在first之前定义了second代码块,也始终会首先打印second

为什么?我如何确保它们将以级联方式执行?

1 个答案:

答案 0 :(得分:6)

因为这是事件处理的工作方式。事件首先从窗口穿过文档到目标元素经历捕获阶段,然后从目标元素到窗口冒泡

您的第一个on调用会在click上附加一个document处理程序,该处理程序在被调用时将检查事件是否在末尾之间通过与.myClass匹配的任何元素传递target和document,如果是,则调用您的处理程序。您的第二个on调用将处理程序直接附加到匹配的元素。在这两种情况下,您都在冒泡阶段(jQuery不支持在捕获阶段)。因此,元素本身的处理程序在文档上匹配的委托处理程序之前被调用。 (从技术上讲,当事件是目标元素中的 时,它处于 target 阶段,而不是捕获或冒泡。但是捕获和冒泡处理程序都是按此顺序进行计算的- —在目标元素上。)

这是来自旧find_program的很棒的多合一图表:

DOM3 Events spec

您可以在当前的enter image description here中找到详细信息。

尽管jQuery不支持捕获阶段,但是DOM4 spec在兼容的浏览器上(因此,不是IE8和更早的版本,没有捕获或addEventListener)。 addEventListener的第三个参数让您决定要捕获(true)还是冒泡(false);它默认为false(在现代系统中,第三个参数可以是带有各种标志的对象)。

下面是一个显示所有阶段事件的示例:

// See: https://www.w3.org/TR/domcore/#dom-event-none
const eventPhases = ["NONE", "CAPTURING_PHASE", "AT_TARGET", "BUBBLING_PHASE"];

function captureHandler(e) {
  console.log("captureHandler: " + eventPhases[e.eventPhase] + " on " + this.id);
}
function bubbleHandler(e) {
  console.log("bubbleHandler:  " + eventPhases[e.eventPhase] + " on " + this.id);
}

function hookBoth(element) {
  element.addEventListener("click", captureHandler, true);
  element.addEventListener("click", bubbleHandler, false);
}

hookBoth(document.getElementById("outer"));
hookBoth(document.getElementById("middle"));
hookBoth(document.getElementById("target"));
<div id="outer">
  <div id="middle">
    <div id="target">Click Me</div>
  </div>
</div>