2

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

5 回答 5

1

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

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

让事件 = 新的自定义事件(类型,[,选项])。

选项有一个标志:气泡,默认为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>

于 2022-02-03T01:12:09.683 回答
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>
于 2016-12-22T17:29:46.087 回答
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 元素(附加到主体)都获得事件(假设没有元素本身停止传播),因此无需知道哪些元素正在侦听或关心事件。这不会分派到每个单独的元素,因为那将是矫枉过正,但只是结束,让冒泡就可以了。

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

于 2016-12-22T17:18:21.157 回答
0

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

于 2016-12-22T16:29:54.980 回答
0

试试这个。使用 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>

于 2016-12-22T16:32:10.467 回答