2016-12-22 2 views
1

Я ожидаю, что мой CustomEvent будет распространен из документа во все элементы DOM. По какой-то причине этого не происходит. Что я делаю не так?Распространение пользовательских событий

<html> 
<script> 
function onLoad() { 
    var myDiv = document.getElementById("myDiv"); 
    myDiv.addEventListener("myEvent",function(){alert("Yes!");}); 
    document.dispatchEvent(new CustomEvent("myEvent",{detail:null})); 
} 
</script> 
<body onload="onLoad()"> 
<div id="myDiv"></div> 
</body> 
</html> 
+0

Да, но я не хочу делать это напрямую. В моем реальном коде структура DOM динамична, элементы приходят и уходят, поэтому я хочу, чтобы обработчики событий были активны только тогда, когда его элемент привязан к DOM. – Rediska

+0

Может быть событие пузырящееся. Вы пробовали 'myDiv.addEventListener (« myEvent », function() {alert (« Да! »), True});' – Shilly

+0

yes Я сделал, как true, так и false. Не помогает. – Rediska

ответ

1

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

<html> 
<script> 
function onLoad() { 
    var myDiv = document.getElementById("myDiv"); 
    myDiv.addEventListener("myEvent",function(){alert("Yes!");}); 
    myDiv.dispatchEvent(new CustomEvent("myEvent",{detail:null})); 
} 
</script> 
<body onload="onLoad()"> 
<div id="myDiv"></div> 
</body> 
</html> 

скрипка: https://jsfiddle.net/yrf9cvr3/

Как распространение работает: Мероприятие начинается в document и работает это путь вниз к элементу он был направлен на (Вы можете захватить событие идет таким образом, используя флаг onCapture). Затем возвращается к document. Поскольку вы отправляете на document, мероприятие действительно не идет никуда, только document посмотреть событие.

+0

Ну, все дело в том, что я не знаю, какие элементы нуждаются в событии. Сами элементы «знают», что им нужно, и соответственно определяют обработчики событий. – Rediska

+0

Я боюсь, это приведет к утечке памяти при удалении элементов из DOM. – Rediska

+0

@TheSharpieOne Используйте [document.querySelector()] (https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector), чтобы указать узел или весь документ, который вы хотите отслеживать. Тогда, если у вас есть динамически созданная страница, это не имеет значения. какой контент вставляется. Из этого вы можете извлечь много материала. Он автоматически передает событие вместе с любой функцией, которую вы хотите запустить. Взгляните на это объяснение [я дал] (http://stackoverflow.com/questions/40618259/mutiple-buttons-with-the-same-name-showing-different-divs/40618656#40618656) на предыдущем посту – Claus

0

Попробуйте этот. Используйте document.querySelector и укажите события, которые вы хотите отслеживать. Нажмите на кнопку или введите текст в текстовом поле

\t <html> 
 
\t <script> 
 
\t function onLoad() { 
 
// \t var myDiv = document.getElementById("myDiv"); 
 
// \t myDiv.addEventListener("myEvent",function(){alert("Yes!");}); 
 
// \t document.dispatchEvent(new CustomEvent("myEvent",{detail:null})); 
 

 
\t \t var myDiv = document.querySelector("#myDiv"); 
 
\t 
 
\t \t myDiv.addEventListener("click", myEventHandler, false); 
 
\t \t myDiv.addEventListener("change", myEventHandler, false); 
 
\t } 
 

 
\t function myEventHandler(e) 
 
\t { 
 
\t \t alert('Element was '+e.target.id+'\nEvent was '+e.type); 
 
\t } 
 
\t </script> 
 
\t <body onload="onLoad()"> 
 
\t <div id="myDiv"> 
 

 
\t <input type="button" id= "Button 1" value="Button 1"><br> 
 
\t <input type="text" id="Text 2"> 
 
\t 
 
\t 
 
\t </div> 
 
\t </body> 
 
    </html>

0

Идущий с крайними. События распространяются вплоть до элемента, на который они отправляются и создаются резервные копии ... Таким образом, чтобы инициировать событие по любому и по существу всем элементам (поскольку неизвестно, какие элементы нуждаются в событии), вы можете найти «концы» всех «филиалы» DOM и отправки им событий.

JQuery позволяет легко выбрать конец ветви

function onLoad() { 
    var myDiv = document.getElementById("myDiv"); 
    myDiv.addEventListener("myEvent", function() { 
    alert("Yes!"); 
    }); 
    $(':not(:has(*))').each(function(i, el){ 
    el.dispatchEvent(new CustomEvent("myEvent", { 
     detail: null, 
     bubbles: true 
    })); 
    }); 
} 

https://jsfiddle.net/dkqagnph/1/

Используя это обеспечит КАЖДЫЙ DOM элемент (крепится к корпусу) получает событие (при условии, что нет распространения элемента остановки) и, таким образом, не нужно знать, какие элементы слушают или заботятся о событии. Это не посылает каждому отдельному элементу, так как это будет излишним, но только конец и позволяет пузыриться.

ПРИМЕЧАНИЕ: элементы с более чем одним ребенком получат событие более одного раза. Возможно, вы захотите, чтобы ваш код запускался более одного раза или его не волнует, если он работает более одного раза.

+0

Ваш пример, вероятно, вызовет событие более одного раза на элементах, которые содержат много дочерних элементов. Во всяком случае, поскольку меня не волнует порядок, в котором событие достигает узлов, я могу просто перейти от вершины. – Rediska

+0

@ Редиска Да, я добавил к этому заметку. Вы могли бы, вероятно, передать уникальный идентификатор вместе с событием, чтобы помочь поймать «одно и то же» событие, возникающее из разных детей – TheSharpieOne

0

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

<html> 
<script> 
document.dispatchCustomEvent = function(event) { 
    function visit(elem,event) { 
    elem.dispatchEvent(event); 
    var child = elem.firstChild; 
    while(child) { 
     if(child.nodeType==1) visit(child,event); 
     child = child.nextSibling; 
    } 
    } 
    visit(document.documentElement,event); 
} 

function onLoad() { 
    var myDiv = document.getElementById("myDiv"); 
    myDiv.addEventListener("myEvent",function(){alert("Yes!");}); 
    document.dispatchCustomEvent(new CustomEvent("myEvent",{detail:null})); 
} 
</script> 
<body onload="onLoad()"> 
<div id="myDiv"></div> 
</body> 
</html> 
Смежные вопросы