Как записывать пользовательские события? - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь создать настраиваемое событие и зафиксировать это событие. Вот мои упрощенные HTML и JavaScript

let parent = document.getElementById('parent');
let child = document.getElementById('child');

parent.addEventListener('custom-event', () => alert("parent"), true);
child.addEventListener('custom-event', () => alert("child"));

let event = new Event('custom-event');
parent.dispatchEvent(event);
<div id="parent">
  <p id="child">
    Hello World
  </p>
</div>

В этом случае я получаю предупреждение «родительский», но не получаю дочернее всплывающее окно.

Однако, если я попробую используя уже существующее событие, такое как «щелчок», оно работает.

let parent = document.getElementById('parent');
let child = document.getElementById('child');

parent.addEventListener('click', () => alert("parent"), true);
child.addEventListener('click', () => alert("child"));
<div id="parent">
  <p id="child">
    Hello World
  </p>
</div>

Есть ли способ / обходной путь, который я могу использовать для захвата пользовательских событий?

Ответы [ 2 ]

0 голосов
/ 16 июня 2020

Как заявил Мориц, вам нужно будет активировать событие для дочернего элемента, поскольку это самый внутренний элемент. Таким образом, событие всплывает до каждого родителя. target события всегда будет дочерним, но currentTarget события будет текущим элементом по мере продвижения вверх по цепочке.

Вы должны убедиться, что useCapture равно true , для элементов-предков, для которых должно быть выбрано событие. См .: EventTarget.addEventListener.

useCapture

A Boolean с указанием, что события этот тип будет отправлен зарегистрированному listener перед отправкой в ​​любой EventTarget под ним в дереве DOM.

События, которые поднимаются вверх по дереву, не будут вызывать слушатель, назначенный для использования захвата. Возврат и захват событий - это два способа распространения событий, которые происходят в элементе, вложенном в другой элемент, когда оба элемента зарегистрировали дескриптор для этого события. Режим распространения события определяет порядок, в котором элементы получают событие. См. DOM Level 3 Events и JavaScript Event order для подробного объяснения. Если не указано, useCapture по умолчанию false.

Если вы удалите параметр useCapture (второй параметр) из parent.addEventListener, только Родителя заберут вслед за ребенком. Цепочка не разорвется, если вы не отмените событие в дочернем элементе.

Примечание: Если вы запускаете неродное событие, предпочтительно использовать конструктор CustomEvent . Опять же, вы можете просто вызвать конструктор напрямую, если хотите. Это просто безопасная оболочка для браузера.

let grandParent = document.getElementById('x-grand-parent');
let parent = document.getElementById('x-parent');
let child = document.getElementById('x-child');

grandParent.addEventListener('custom-event', (e) => console.log(e.currentTarget.id), true);
parent.addEventListener('custom-event', (e) => console.log(e.currentTarget.id), true);
child.addEventListener('custom-event', (e) => console.log(e.currentTarget.id));

triggerCustomEvent(child, 'custom-event');

function triggerCustomEvent(el, eventName, options) {
  let opts = Object.assign({
    canBubble: true,
    cancelable: true,
    detail: {}
  }, options);
  let event = null;
  if (window.CustomEvent && typeof window.CustomEvent === 'function') {
    event = new CustomEvent(eventName, {
      detail: opts.detail
    });
  } else {
    event = document.createEvent('CustomEvent');
    event.initCustomEvent(eventName, opts.canBubble, opts.cancelable, opts.detail);
  }
  el.dispatchEvent(event);
}
<div id="x-grand-parent">
  <div id="x-parent">
    <p id="x-child">
      Hello World
    </p>
  </div>
</div>
0 голосов
/ 16 июня 2020

Попробуйте отправить событие на дочерний узел, и вы получите оба предупреждения.

let parent = document.getElementById('parent');
let child = document.getElementById('child');

parent.addEventListener('custom-event', () => alert("parent"), true);
child.addEventListener('custom-event', () => alert("child"));

let event = new Event('custom-event');
child.dispatchEvent(event);
<div id="parent">
  <p id="child">
    Hello World
  </p>
</div>
...