2015-04-11 2 views
5

У меня есть родитель <div> с одним ребенком <div> в памяти - не привязан к текущему документу. Я хочу вызвать CustomEvent на дочерний элемент, но выслушайте это событие от родителя. Вот мой код:Почему не происходит барботирование событий в отдельных элементах DOM?

var parent = document.createElement('div'); 
var child = document.createElement('div'); 
parent.appendChild(child); 
parent.addEventListener('boom', function(event) { 
    console.log('parent listener', event); // <~ This never runs! 
}); 
var event = new CustomEvent('boom', { bubbles: true }); 
child.dispatchEvent(event); 

Этот код не работает должным образом. Слушатель событий родителя никогда не срабатывает. Это, похоже, противоречит системе событий JavaScript, в результате которой события выходят из цели. Однако, если я изменить две последние строки этого фрагмента в следующих случаях обратного вызова срабатывает, как я бы ожидать, что это:

document.body.appendChild(parent); 
child.dispatchEvent(event); 

Другими словами, если я прилагаю мой фрагмент в качестве поддерева документа перед отправкой событие, то прослушиватель родительского события срабатывает точно так, как ожидалось. Зачем? Есть ли способ разрешить пузырение при использовании отдельных элементов DOM?

+1

Я не вижу виртуального DOM здесь, виртуальный DOM обычно означает DOM, который на самом деле не DOM - ваш DOM здесь очень реальный, просто отсоединенный. –

+0

Кроме того, вот решение https://medium.com/@webprolific/bubbling-events-in-detached-dom-trees-35c34b551723, если это решит проблему, напишите ответ для будущих посетителей :) –

+0

@RobG это объектная модель документа, она представляет, как вы взаимодействуете с документами через API-интерфейс объекта, элемент с дочерним элементом, безусловно, является объектом, который указывает на взаимодействие с документом, а документ больше, чем просто дерево dom. AJAX и т. Д. Также являются частью DOM API, а также являются веб-мастерами. –

ответ

4

Почему [не работает пузырь по отдельным элементам]?

Чтобы ответить на ваш первый вопрос, я просмотрел W3C "UI Events (formerly DOM Level 3 Events)" spec и не видел ничего, что конкретно касалось этой проблемы. Однако в части event phase упоминается несколько вещей, которые делают это поведение разумным.

В качестве следующего шага объект события должен заполнить одну или несколько фаз событий. Эта спецификация определяет три фазы событий: фазу захвата, целевую фазу и фазу пузырьков. Объекты событий заполняют эти фазы в указанном порядке, используя пути частичного распространения, как определено ниже. Фаза должна быть пропущена, если она не поддерживается, или если распространение объекта события остановлено. Например, если для атрибута Event.bubbles установлено значение false, фаза пузыря будет пропущена, и если событие Event.stopPropagation() было вызвано до отправки, все фазы должны быть пропущены.

Emphasis mine.

Спецификация затем переходит к списку фаз:

  1. захвата фаза: Объект события должен распространяться через его предок, от окна к родителю целей. Эта фаза также известна как фаза захвата. Слушатели событий, зарегистрированные для этой фазы, должны обработать событие до того, как оно достигнет цели.
  2. Целевой этап : Объект события должен прибыть к объекту события объекта события. Эта фаза также известна как фаза цели. Слушатели событий, зарегистрированные для этой фазы, должны обработать событие, как только оно достигнет цели. Если тип события указывает, что событие не должно пузыриться, объект события должен остановиться после завершения этой фазы.
  3. пузырьковая фаза: Объект события распространяется через предков цели в обратном порядке, начиная с родителя цели и заканчивая окном. Эта фаза также известна как фаза барботирования. Слушатели событий, зарегистрированные для этого этапа, должны обработать событие после достижения цели.

Снова, акцент мой. Спектр никогда не вызывает явно то, что происходит с отдельными элементами. Учитывая, что для фаз мишени и пузырьков требуется путь перехода от элемента к окну и что для отдельных элементов не существует пути, из этого следует, что фазы события цели и пузырька должны быть пропущены, поскольку эти пути не поддерживаются.

Есть ли способ разрешить пузыри при использовании отдельных элементов DOM?

Насколько я могу судить, нет ничего встроенного, что позволило бы пузыриться. Возможно, вы сможете подделывать пузырьки с помощью какого-то пользовательского кода, но для этого потребуется проверка того, будет ли элемент отсоединен каждый раз при запуске события.

Еще одна мысль - добавить элементы в DOM, вызвать событие и отсоединить элементы. Поскольку я не тестировал это, я понятия не имею, будет ли это работать.

+0

Я предполагаю, что фраза есть только там, чтобы сделать IE совместимым, который не поддерживает фазу захвата. – Bergi

+0

Это отличный ответ, и я согласен с тем, что, хотя спецификация не является явной о поведении в этой ситуации, действительно имеет смысл, что этого не происходит. В любом случае реализация пузырька событий «вручную» достаточно проста: просто отправьте объект события на каждый «parentNode», начиная с нужной цели, d, пересекая верхнюю часть отдельного дерева. – GladstoneKeep

+0

@GladstoneKeep, это кажется достаточно простым, но вы все равно должны помнить, чтобы назначить правильные свойства «target» и 'currentTarget' для события. Для меня это похоже на много накладных расходов для поддержки. – zzzzBov

Смежные вопросы