Javascript 自定义事件的传播

Javascript 自定义事件的传播,javascript,html,dom,event-propagation,custom-event,Javascript,Html,Dom,Event Propagation,Custom Event,我希望CustomEvent从文档传播到所有DOM元素。 由于某种原因,它没有发生。我做错了什么 <html> <script> function onLoad() { var myDiv = document.getElementById("myDiv"); myDiv.addEventListener("myEvent",function(){alert("Yes!");}); document.dispatchEvent(new CustomEvent(

我希望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>

函数onLoad(){
var myDiv=document.getElementById(“myDiv”);
addEventListener(“myEvent”,function(){alert(“Yes!”;});
dispatchEvent(新的CustomEvent(“myEvent”{detail:null}));
}

您必须将事件分派到要“触发”事件的元素上。然后它将向下传播并备份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>

函数onLoad(){
var myDiv=document.getElementById(“myDiv”);
addEventListener(“myEvent”,function(){alert(“Yes!”;});
myDiv.dispatchEvent(新的CustomEvent(“myEvent”{detail:null}));
}
小提琴:


传播方式:事件从
文档开始,一直到它被分派到的元素(您可以使用
onCapture
标志捕获这样的事件)。然后返回到
文档
。因为您在
文档上调度事件,所以事件实际上不会发生在任何地方,只有
文档
可以看到事件。

试试这个。使用document.querySelector并指定要跟踪的事件。单击按钮或在文本框中键入一些文本


函数onLoad(){
//var myDiv=document.getElementById(“myDiv”);
//addEventListener(“myEvent”,function(){alert(“Yes!”;});
//dispatchEvent(新的CustomEvent(“myEvent”{detail:null}));
var myDiv=document.querySelector(“myDiv”);
myDiv.addEventListener(“单击”,myEventHandler,false);
myDiv.addEventListener(“更改”,myEventHandler,false);
}
函数myEventHandler(e)
{
警报('元素为'+e.target.id+'\n事件为'+e.type');
}


走极端。事件向下传播到它们所调度和备份的元素。。。因此,为了在任何元素上触发事件(因为不知道哪些元素需要事件),您可以找到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
    }));
  });
}

使用它将确保每个DOM元素(连接到主体)都获得事件(假设没有元素停止传播本身),因此不需要知道哪些元素正在侦听或关心事件。这并不是分派到每个单独的元素,因为那样做可能会有点过头,但这只是结束,让冒泡完成它的任务


注意:具有多个子元素的元素将多次获取事件。您可能需要一种方法来确保您的代码运行不止一次,或者不关心它是否运行不止一次。

我发布了一些解决方案,而不是真正的答案。 这将向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>

document.dispatchCustomEvent=函数(事件){
功能访问(要素、活动){
要素调度事件(事件);
var child=elem.firstChild;
while(儿童){
if(child.nodeType==1)访问(child,event);
child=child.nextSibling;
}
}
访问(文档、文档元素、事件);
}
函数onLoad(){
var myDiv=document.getElementById(“myDiv”);
addEventListener(“myEvent”,function(){alert(“Yes!”;});
dispatchCustomEvent(新的CustomEvent(“myEvent”{detail:null}));
}

是的,但我不想直接这样做。在我的实际代码中,DOM结构是动态的,元素来来往往,所以我希望事件处理程序只有在其元素连接到DOM时才处于活动状态。可能是一个冒泡事件。您是否尝试过
myDiv.addEventListener(“myEvent”,function(){alert(“Yes!”),true})是的,我做了,对和错。没有帮助。这是一个完整且可验证的示例。如果事件已传播,则应看到“是!”警报。只需复制代码并在浏览器中运行。@Rediska我提供的小提琴修复了您的代码即可。如果这是一个答案,那么答案将是正确的。完整的示例表明您知道要在哪个元素上触发事件。如果不是,那么我给出的关于事件传播工作原理的解释将表明,根据您提供的信息,您不可能做您想要做的事情。好吧,关键是我不知道哪些元素需要事件。元素本身“知道”它们需要什么,并相应地定义事件处理程序。我担心,当从DOM中删除元素时,这会导致内存泄漏。@SharpieOne用于指定要跟踪的节点或整个文档。然后,若您已经动态创建了页面,那个么这并不重要。插入了什么内容。你可以从中检索到很多东西。它会自动将事件传递给您想要运行的任何函数。请看一下上一篇文章中的解释,使用document.querySelector()并不比只对DOM的每个元素调用dispatchEvent好多少。我有点希望这个功能已经到位了。@TheSharpieOne。使用查询选择器,您不需要知道发生了哪些事件。使用路由器功能来引导您的流量。他将添加/删除内容。只要查询选择器绑定到包含他所需要的元素的容器。在子函数中,他可以测试激活事件的对象的任何属性、值等。您的示例可能会在具有多个子元素的元素上多次触发事件。无论如何,因为我不关心事件到达节点的顺序,所以我可以从顶部开始。@Rediska是的,我添加了一条关于这一点的注释。您可能会在事件中传递一些唯一的id,以帮助捕获来自不同子级的“相同”事件