Preface: this article is a little long, please read attentively, after I believe will solve your many doubts.

Let’s start with a toy demo.

// dom level
  -> div (onclick)
    -> p
      -> span
Copy the code

Question 🤔 : Why is the click event also triggered when we click

?

Bubbling.

Bubbling is a transmission mechanism for events. When an event occurs, the event propagates through the target parent in reverse order, ending with Window.

Take the previous example 🌰, where when the user clicks on the element, the event fires click events from the bottom up (child elements -> ancestors). And almost all events have a bubbling phase.

Capture = Capture

We know that in addition to bubbling, one of the delivery mechanisms for events that we often talk about is capture.

Actually this is not completely correct!! According to the W3C definition, event delivery is divided into three stages:

  1. Capture: Event objects are propagated through the Window to the target’s ancestor and parent to itself.

  2. Target: The event object reaches the Target itself, and when the event type is specified not Bubble, the event terminates at this stage (explained later).

  3. Bubble: Event objects propagate through the target’s parent ancestors in reverse order, ending with Window.

So the standard transfer flow when an event occurs isCapture -> Target -> Bubble

We use it in HTML when our program runs in a major browseron[eventType]Or in javascriptelement. addEventListener(eventType, listener)These Web apis seem to ignore the capture phase and only run the target phase and the bubble phase.

Question 🤔 : Then a question arises at this time? If we add events to a nested Dom separately, we cannot change the order in which events are emitted (events bound to child elements are emitted before events bound to parent elements). How can we change the order?

EventListener Option -“options ={} | useCapture = boolean 】

Thanks to the completeness of the 🙏 Web API, if you look at the definition of the addEventListener API, you will see that declarations have a third parameter option, which can be passed in as a Boolean or an object.

elem.addEventListener(type, listener[, options]);
elem.addEventListener(type, listener[, useCapture]);
Copy the code

So when you add an event listener to an element, you can write:

elem.addEventListener(_, _, {capture: true})
// The object form also accepts more options :[once,...]
/ / or
elem.addEventListener(_, _, true)
Copy the code

They are equivalent, indicating that the listening callback will be triggered during the capture phase. So that way we can solve the problem above. Such as:

// dom level
  -> div (onclick= log('div'.true))
    -> p (onclick = log('p'Div -> p // instead -> div (onclick=log('div'))
    -> p (onclick = log('p'// The output order is p -> divCopy the code

listener callback param – Event

First of all, a listener can be passed not only as a function but also as an object that implements the Event interface (including the handleEvent(fn) property). We won’t explain it here, see the documentation for more details.

Next, let’s talk more about the parameter Event, or e, passed in when the listener is called

e.target

// dom level
  -> div (onclick)
    -> p
      -> span
Copy the code

Again using the previous example, we explain a few mistakes (there may be errors here 🙅, hope the big guy found not hesitate to correct) :

⚠️ Myth 1: When

adds a click event, does it mean

? also adds a click event

A: ❌, the fact that you add click to

has nothing to do with its child element, but you can get the actual object that triggered the Event through the Event object, which looks as if the child element of

also added the Event listener. Remember that the callback occurs on the target element to which the event was added (click’s Listener callback occurs on a div).

⚠️ Myth 2: Since event delivery is capture -> target -> bubble, why doesn’t a click event fire more than once?

A: We know from the addEventListener API that events can be bound to the bubble or capture phase. When this is not set, the default is the bubble phase and only fires once, during the corresponding binding phase.

Note: Since adding an event is a differentiated phase, you need to specify the corresponding phase when removing this event.

When an event is triggered, the value of e.target (read-only) is the most deeply nested associated element and does not necessarily correspond to the element to which the event was added. For example, in the appeal example, when you click on the event-passing bubble goes to the

element whose click event callback is triggered, and the value of e.target is the SPAN element object.

e.currentTarget

We know that e.target (read-only) does not necessarily correspond to the element that added the event, so how do we know in the callback which element added the event listener? This is e.currenttarget, and you can also use this directly inside the listener method, which is equivalent to (this = event.currenttarget).

e.path

E. path (read-only) is an array eg: [span, p, div, body, HTML, document, Window] it represents the element hierarchy from e.target to Window.

e.stopPropagation()

When we talked about the capture phase in the event pass phase, we mentioned that you can terminate early and not do the bubble phase. You can call e.topPropagation () when the listener event callback added in the capture phase is called to prevent further propagation of the event in the DOM. For historical reasons it is also possible to call e.cancelbubble = true to prevent event bubblings (this property is not recommended, stopPropagation is preferred)

e.[other]

There are many other attributes on the Event object, and I won’t list them all here. The most commonly used attributes are basically the above ones. There is a lot more information available on the other attributes, but some attributes may not be standard


Here are some tips on EventListener: 👆

If there is anything not covered, welcome to discuss it.


Why write this ?

Mainly due to my recent [BCZ] interview experience related to the hair:

First, when I mentioned this topic in the interview, I forgot many details due to my poor skills, and finally failed in the interview. The main problem is me, which makes me want to re-record.

Second, I respect the concept of each company, but it does not mean THAT I recognize. After the [BCZ] interview, I think your company has a lot of problems in the interview, which gives me the feeling that a company pays special attention to the basics (there is nothing wrong with paying attention to the basics). Taking the interviewer himself as an example, I can feel that the interviewer is not deep enough in knowledge through communication. The acquisition of knowledge should always be in awe, since you attach great importance to the basics you had better be authoritative, otherwise how do you evaluate the volume in the semi-irrigation? If you give the interviewer that feeling, I can only assume that you are interviewing for the sake of interviewing. This should not be teaching to the test.

And three, my autism might be alleviated.