自定义事件的传播

Propagation of custom events

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

你必须在你想要事件 'triggered' 的元素上发送事件。然后它将向下传播并备份 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>

fiddle: https://jsfiddle.net/yrf9cvr3/

传播的工作原理:事件从 document 开始,一直向下传播到它被分派到的元素(您可以使用 onCapture 标志捕获以这种方式进行的事件)。然后回到 document。因为您是在 document 上调度,所以事件实际上并没有去任何地方,只有 document 看到了事件。

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

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

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

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

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

走极端。事件向下传播到它们被分派的元素并备份...所以为了在任何和基本上所有元素上触发事件(因为不知道哪些元素需要事件)你可以找到 "ends" DOM 的所有 "branches" 并向它们发送事件。

jQuery方便select结束分支

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 元素(附加到正文)获得事件(假设没有元素停止传播本身),因此不需要知道哪些元素正在监听或关心事件。这不会分派到每个单独的元素,因为那样会有点矫枉过正,但只是结束并让冒泡完成它的事情。

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

我发布的是一些解决方案,并不是真正的答案。 这会将自定义事件传播到 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>

默认情况下,自定义事件不会冒泡。

原因是,自定义事件定义说:

let event = new CustomEvent(type,[options]).

选项有一个标志:bubbles,即false 默认情况下,我们必须启用它。

以下将修复您的代码

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