Почему $ ('. MyClass'). On ("input propertychange", function () {}) всегда вызывается перед $ (document) .on ("input propertychange", ".myClass", function () {))? - PullRequest
0 голосов
/ 06 сентября 2018

Вот рабочий пример:

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

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

Даже если я определю блок кода first перед second, всегда сначала печатается second.

Почему? И как я могу гарантировать, что они будут выполняться каскадом?

1 Ответ

0 голосов
/ 06 сентября 2018

Потому что так работает обработка событий. События сначала проходят фазу capture из окна через документ к целевому элементу, а затем bubble из целевого элемента в окно.

Ваш первый вызов on присоединяет обработчик click к document, который при вызове проверяет, прошло ли событие какие-либо элементы, соответствующие .myClass между конечной целью и document, и, если Итак, вызывает ваш обработчик. Ваш второй вызов on присоединяет обработчик непосредственно к соответствующему элементу (ам). В обоих случаях вы подключаете фазу пузырьков (jQuery не поддерживает подключение фазы захвата). Таким образом, обработчик самого элемента вызывается перед соответствующим делегированным хандером в документе. (Технически, когда событие в целевом элементе, оно находится в фазе target , не в захвате и не в пузырях. Но и обработчики захвата, и пузырьки обрабатываются & mdash; и в этом порядке & mdash ; на целевом элементе.)

Вот отличная диаграмма "все в одном" из старой спецификации DOM3 Events :

enter image description here

Подробности можно найти в текущей спецификации DOM4 .

Хотя jQuery не поддерживает фазу захвата, addEventListener поддерживает совместимые браузеры (то есть не 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...