When I was learning the event mode, I could not remember the event propagation process and the setting details of addEventListener. Later, I found that a good picture could help us understand logos better, so I made a GIF.

Event propagation mode

Suppose we now have three DOM nodes, and assume that div is the root node. (Usually events are captured from the root node.)

We then set up listeners for these DOM nodes.

// Setting the third parameter to true triggers the capture phase
div.addEventListener('click'.null.true);
p.addEventListener('click'.null.true);
span.addEventListener('click'.null.true);

span.addEventListener('click'.null);
p.addEventListener('click'.null);
div.addEventListener('click'.null);
Copy the code

Now we click on span, and the Click event will be triggered. The event will enter the capture phase from the div, passing from parent to child, and when it reaches the event target it will enter the bubble phase, passing from child to parent.

(click)span => div -> p -> span -> span -> p -> div

If we click p, the event target is the P element, the event is captured from the div element, and it bounts back from the P element to bubble.

(click)p => div -> p -> p -> div

Multiple binding

If listeners for the same event are bound multiple times on a node, they follow the event propagation process (catch then bubble), and bind first, fire first if the process is the same.

// Setting the third parameter to true triggers the capture phase
div.addEventListener('click'.null.true) / / # 1
div.addEventListener('click'.null)       / / # 2
div.addEventListener('click'.null.true) / / # 3

p.addEventListener('click'.null.true);
p.addEventListener('click'.null);
Copy the code

(click)p => div#1 -> div#3 -> p -> p -> div#2

Although the order of claim is div#1 div#2 div#3, capture precedes bubbling, so div#1 div#3 fires sequentially, while div#2 fires during bubbling.

stopPropagation

This is a method of the Event object that prevents the Event from propagating further.

// Setting the third parameter to true triggers the capture phase
/ / # 1
div.addEventListener('click'.function (event) {
  event.stopPropagation();
}, true) 
div.addEventListener('click'.null)       / / # 2
div.addEventListener('click'.null.true) / / # 3

p.addEventListener('click'.null.true);
p.addEventListener('click'.null);
Copy the code

(click)p => div#1 -> div#3

After using stopPropagation(), events cannot propagate further. Even on divs, capture and bubble are considered two steps, so bubbles on the same node do not fire if propagation is blocked during capture.

stopImmediatePropagation

This is a method of the Event object that, once called, will not fire any unfired listeners on the element and the Event will not propagate further.

Now let’s add one more event listener to the div and add stopImmediatePropagation to the second listener that was triggered in the capture event.

// Setting the third parameter to true triggers the capture phase
div.addEventListener('click'.null.true) / / # 1
div.addEventListener('click'.null)       / / # 2
/ / # 3
div.addEventListener('click'.function (e) {
  e. stopImmediatePropagation();
}, true)
div.addEventListener('click'.null.true) / / # 4

p.addEventListener('click'.null.true);
p.addEventListener('click'.null);
Copy the code

(click)p => div#1 -> div#3

After using stopImmediatePropagation(), even the listeners waiting to be triggered in the current node were silenced.

Further reading

In newer browsers, addEventListener supports more parameter configurations, and the third parameter type supports object.

target.addEventListener(type, listener[, options]);

This option supports three fields

  • capture BooleanWhether to trigger in capture mode
  • once BooleanWhether to trigger only once
  • passive BooleanWhether to use passive mode

Here’s how once works

// Setting the third parameter to true triggers the capture phase
div.addEventListener('click'.null.true);
p.addEventListener('click'.null.true);
span.addEventListener('click'.null.true);

span.addEventListener('click'.null);
p.addEventListener('click'.null, {once: true}); // Only fires once during the bubbling phase
div.addEventListener('click'.null);
Copy the code

(click)span => div -> p -> span -> span -> p -> div

(click)span => div -> p -> span -> span -> div

Demo

JSbin

Luo Xiaohei writes

If you like the article please leave a like ~ if you like the article to share to more people ~

Follow me in nuggets follow me in Jane’s book

Free reprint – Non-commercial – Non-derivative – Keep attribution (Creative Commons 3.0 License) Please keep the link to the original article when reprint to ensure timely access to corrections and amendments to the article