[Javascript] Event propagation: useCapture for addEventListener

发布时间 2023-06-20 14:19:45作者: Zhentiw

What gets logged when clicking button?

<div id="outer">
  <div id="inner">
    <button id="btn">Click me!</button>
  </div>
</div>
const outer = document.getElementById("outer");
const inner = document.getElementById("inner");
const button = document.getElementById("btn");

outer.addEventListener("click", () => console.log("A"), true);
outer.addEventListener("click", () => console.log("B"));
inner.addEventListener("click", () => console.log("C"), true);
inner.addEventListener("click", (e) => {
  console.log("D");
  e.stopPropagation();
  console.log("E");
});
button.addEventListener("click", () => console.log("F"));
button.addEventListener("click", () => console.log("G"), true);

 

There are three phrases during event propagation:

  1. Capturing: Event goes down from top to bottom of the DOM tree, you don't get access to event.target
  2. Targeting: When event reach the target element, it is targeting
  3. Bubbling: Then event goes up through the tree, is bubbling, you get access to event.target

 

outer.addEventListener("click", () => console.log("B")); // this event only get trigger in bubbling
outer.addEventListener("click", () => console.log("A"), true); // this evnet fire during capturing

 

That's why A -> C -> G will be logged first during capturing phrase.

Then Fis targeting

D -> E is bubbling, since we call stopPropagation, `B` won't be logged.

 

Answer: A -> C -> G -> F -> D -> E

 

stopPropagationvs  stopImmediatePropagation
 
outer.addEventListener("click", () => console.log("A"), true);
outer.addEventListener("click", () => console.log("B"));
inner.addEventListener("click", () => console.log("C"), true);
inner.addEventListener("click", (e) => {
  console.log("D");
  e.stopPropagation();
  console.log("E");
});
inner.addEventListener("click", () => console.log("C2")); // <-- new
button.addEventListener("click", () => console.log("F"));
button.addEventListener("click", () => console.log("G"), true);

A -> C -> G -> F -> D -> E -> C2

 

outer.addEventListener("click", () => console.log("A"), true);
outer.addEventListener("click", () => console.log("B"));
inner.addEventListener("click", () => console.log("C"), true);
inner.addEventListener("click", (e) => {
  console.log("D");
  e.stopImmediatePropagation();
  console.log("E");
});
inner.addEventListener("click", () => console.log("C2")); // <-- new
button.addEventListener("click", () => console.log("F"));
button.addEventListener("click", () => console.log("G"), true);

A -> C -> G -> F -> D -> E

stopImmediatePropagationwill stop the rest listeners event to be triggered, since C2is registered after, it won't be triggered.