Here's一个工作示例:
$(document).on("input propertychange", ".myClass", function () {
$('#result').append("first<br />");
});
$('.myClass').on("input propertychange", function () {
$('#result').append("second<br />");
});
即使我在first
之前定义了second
代码块,也始终会首先打印second
。
为什么?我如何确保它们将以级联方式执行?
答案 0 :(得分:6)
因为这是事件处理的工作方式。事件首先从窗口穿过文档到目标元素经历捕获阶段,然后从目标元素到窗口冒泡。
您的第一个on
调用会在click
上附加一个document
处理程序,该处理程序在被调用时将检查事件是否在末尾之间通过与.myClass
匹配的任何元素传递target和document
,如果是,则调用您的处理程序。您的第二个on
调用将处理程序直接附加到匹配的元素。在这两种情况下,您都在冒泡阶段(jQuery不支持在捕获阶段)。因此,元素本身的处理程序在文档上匹配的委托处理程序之前被调用。 (从技术上讲,当事件是目标元素中的 时,它处于 target 阶段,而不是捕获或冒泡。但是捕获和冒泡处理程序都是按此顺序进行计算的- —在目标元素上。)
这是来自旧find_program
的很棒的多合一图表:
尽管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>