En forenklet forklaring af begivenhedsformering i JavaScript.

Forestil dig dette scenarie:

Du bygger en liste over brugere. Du viser deres navne, yndlingsfarver og e-mails. Når du klikker på en bruger (en række i tabellen), vil du have det til at føre dig til brugeroptegnelsen. Bortset fra når du klikker på e-mail, skal den åbne en e-mail-dialog.

Du skriver muligvis en kode som denne (vi bruger en tabel her, fordi den er let at forstå - selvom vi selvfølgelig måske bruger noget meget mere kompliceret i vores projekt):


    
Name Colors Email
Susie Blue, Red [email protected]

Hvis du vil klikke på en af ​​disse rækker, tilføjer du sandsynligvis en onClickfunktion til rækken. På den måde, hvis de klikker et vilkårligt sted i rækken, kan de gå direkte til brugeroptegnelsen.

For at tage os af e-mailen laver vi en ef> tag on the text.

But wait! The email dialog pops up, but we also navigate to the user record. That’s not what we want! How do we handle this? Enter event propagation.

Event propagation in a nutshell.

Event propagation is a way to describe the “stack” of events that are fired in a web browser. In our table example above, clicking on the a tag is the first event that we will fire, but there are other events too.

To understand that concept, you must understand that the elements on a web browser are nested. They do not cover each other up. So a click on the a tag also clicks on the row, the table, the div in which the table is nested, and anything else all the way out to document , the complete container that holds everything in your browser.

If we’ve put any other onClick events inside of these other elements, they will also be fired when we click on the a link in the table. That’s why we will be directed to the user record when we click on the email link. It’s going to perform both the onClick function for the a link and the onClick function for the row.

Bubbles

The movement of events “up” from the most-nested element ( a) out to the least-nested ( document) is referred to as “bubbling.” If events start in the “outer-most” element and moved “down,” that is referred to as “trickling.” All you probably care about is the default behavior: bubbling.

How to use event propagation to your advantage

Honestly, I hadn’t run into any use-case for caring about event propagation until this week, when I needed to build a table with a checkbox in it. Unfortunately for me, when I tried to set up the checking functionality, it took me to the record. Fortunately, I did some training earlier (see references below) that gave me a clue on exactly what I had to Google.

You probably already know that when you create an onClick event, it is passed to whatever function you call.

So here, I was able to write:

handleCheck = e => { e.stopPropagation() // talk to my API, set the record as "done" or not } []

That e.stopPropagation() halts this “bubbling” of events “up” through the DOM. We stop all of the other events in the stack. Awesome!

So my whole row gets to behave as it should, and this one little checkbox can have a special functionality.

preventDefault vs. stopPropagation

You may be thinking: why not just use e.preventDefault()? That is indeed the first thing I tried, but there simply is no default behavior for a span (unlike a form, whose default submit behavior will refresh the page).

Cut-and-paste example

I write a lot of React, so I’m giving an example in React. But this would work the same in plain old HTML and JavaScript, using whatever method you’ve got to add event listeners:

 console.log('outer div')}> console.log('middle div')}> console.log('innermost div')}> Click me! 

Event propagation: bubbles without the champagne.

References

  • Big shouts to Wes Bos who first introduced me to this concept in his #Javascript30 course. I would have had no idea what to Google when I ran into the problem identified in the table example above if I hadn’t first seen it during the course.
  • This Stack Overflow answer, which nicely sums up some of the more nuanced bits of event capture and propagation.