Использование DOMElement.addEventListener в компоненте Vue захватывает предыдущее событие

У меня есть компонент Vue, который в своем методе жизненного цикла created добавляет в документ прослушиватель событий для захвата любых кликов, которые находятся за пределами корня $el. Назовем это Popup

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

Вот jsfiddle с упрощенным кодом: https://jsfiddle.net/awei01/5vuqjcxd/

И, напротив, вот чистая версия js, которая правильно связывает событие клика: https://jsfiddle.net/awei01/qzqku0w9/

В качестве перекрестной ссылки, вот сообщение на форумах vue: https://forum.vuejs.org/t/document-addeventlistener-captures-a-click-preceding-listeners-creation/11558

Любое понимание ценится.


person awei    schedule 23.05.2017    source источник


Ответы (1)


Кредит принадлежит Vue члену основной команды LinusBorg.

Нужен setTimeout

https://forum.vuejs.org/t/document-addeventlistener-captures-a-click-preceding-listeners-creation/11558

Вот рабочий пример с реализованным setTimeout: https://jsfiddle.net/awei01/ovr9sr6k/

Объяснение на английском:

  1. Событие щелчка происходит и переходит в фазу capture. parent Компонент Vue обрабатывает это событие.
  2. Компонент parent устанавливает внутренний флаг $data для отображения модуля popup
  3. Модуль popup создается и монтируется. В функции created присоединяется событие document.addEventListener.
  4. Фаза события клика capture завершается и начинает всплывать DOM.
  5. Событие щелчка теперь захватывается document из-за только что добавленного прослушивателя событий. Он запускает обратный вызов, и похоже, что ничего не произошло.

Решение:

  1. Событие щелчка происходит и переходит в фазу capture. parent Компонент Vue обрабатывает это событие.
  2. Компонент parent устанавливает внутренний флаг $data для отображения модуля popup
  3. Модуль popup создается и монтируется. В функции created присоедините document.addEventListener к функции setTimeout, чтобы она была присоединена после полного завершения события click.
  4. Фаза события клика capture завершается и начинает всплывать DOM.
  5. Фаза bubble события завершена
  6. Обратный вызов в setTimeout теперь выполняется, и документ теперь прослушивает щелчки.
  7. Все последующие клики, всплывающие до document, будут зафиксированы.
person awei    schedule 23.05.2017
comment
Не могли бы вы добавить более подробное объяснение того, как вы будете использовать setTimeout для решения своей проблемы? - person thanksd; 24.05.2017
comment
@Спасибо д. Задержка с ответом на 2 года... дело в скрипке: jsfiddle.net/awei01/ovr9sr6k - person awei; 31.05.2019