Порядок вызванных событий - PullRequest
1 голос
/ 30 апреля 2020

Есть <div> с двумя классами. Для каждого класса существует триггерное событие при нажатии, отдельное событие для каждого класса. Есть ли способ убедиться, что событие для класса class_one всегда будет запущено первым и всегда будет запускаться console.log("First") первым.

$('body').on('click', '.class_one', function() {
  console.log("First")
})

$('body').on('click', '.class_two', function() {
  console.log("Second")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="class_one class_two">Click me</div>

1 Ответ

3 голосов
/ 30 апреля 2020

События не инициируются в классах, а в элементах. Если классы "class_one" и "class_two" установлены для одного и того же элемента, то события вызываются в том же порядке, в котором они связаны. Однако события всплывают, что означает, что событие «click» сначала вызывается при нажатии элемента, затем его родительском элементе и т. Д.

Это означает, что если у вас есть возможность изменить DOM, вы можете принудительно вызвать события на элемент с классом "class_one" должен быть запущен первым. Это можно сделать, удалив класс «class_two» из элемента и обернув его вокруг элемента «class_one».

Это поведение можно найти, описанное в jQuery on документация:

Когда предоставляется selector, обработчик события упоминается как делегированный . Обработчик вызывается не тогда, когда событие происходит непосредственно в связанном элементе, а только для потомков (внутренних элементов), которые соответствуют селектору. jQuery накапливает событие от цели события до элемента, к которому прикреплен обработчик (т. Е. От самого внутреннего к внешнему элементу), и запускает обработчик для любых элементов на этом пути, соответствующих селектору.

$('body').on('click', '.class_one', function() {
  console.log("First")
})

$('body').on('click', '.class_two', function() {
  console.log("Second")
})

$('body').on('click', '.class_one', function() {
  console.log("Third")
})

$('body').on('click', '.class_two', function() {
  console.log("Fourth")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="class_two">
  <div class="class_one">Click me</div>
</div>

Как уже сказано выше: если классы "class_one" и "class_two" установлены в одном элементе, то события вызываются в том же порядке они были связаны.

Что также можно найти в документации on:

Обработчики событий, связанные с элементом, вызываются в том же порядке что они были связаны.

Это свойство можно использовать для регистрации двух событий, которые действуют как «регистр», и запускают все события, добавленные в этот «регистр» (простой массив в примере).

Это решение не требует от вас изменения DOM, но вместо этого требует, чтобы вы изменили регистрацию события в JavaScript.

const class_one_click_fns = [],
      class_two_click_fns = [];

$('body').on('click', '.class_one', function(...args) {
  class_one_click_fns.forEach(fn => fn.call(this, ...args))
})

$('body').on('click', '.class_two', function(...args) {
  class_two_click_fns.forEach(fn => fn.call(this, ...args))
})

class_one_click_fns.push(function () {
  console.log("First")
})

class_two_click_fns.push(function () {
  console.log("Second")
})

class_one_click_fns.push(function () {
  console.log("Third")
})

class_two_click_fns.push(function () {
  console.log("Fourth")
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="class_one class_two">Click me</div>
...