DOM event system

DOM event system

You need to master the basic skills related to the DOM event system from the following aspects

  • DOM event flow
  • Event object
  • Event agent
  • Custom event

DOM event flow

Pre-knowledge

Before understanding the flow of events, we must first have a precise understanding of the following three terms

  1. Event flow: It describes the sequence of events propagating on the page.
  2. Event: It describes the actions that occur in the browser. This action can be triggered by the user or the browser. Events like click, mouseover, mousemove are all events.
  3. Event monitoring function: how the browser responds after the event occurs-the function used to respond to the event is the event monitoring function, also called the event handler.

The evolution of the event stream

The current widely accepted JS event stream specification is not achieved overnight. In the early years, two browser vendors, IE and NetScape, competed hard for you in the design of the event mechanism, and no one recognized anyone. IE proposes bubbling streams, while NetScape only recognizes capture streams. The two companies did their own things, and it was difficult for the front-end programmers to have a hard time. Every time they did web page compatibility adaptation, they burst into tears. Fortunately, the righteous W3C stepped in. Under the unified organization of the W3C, JS supports both the bubbling stream and the capture stream, and uses this as the exact event stream standard. This standard is also called "DOM2 Event Stream" . We don t talk about non-standard ones. All of our discussion below will focus on the DOM2 event stream that is firmly established.

A trip to an event

The W3C standard stipulates that the propagation process of an event must go through the following three stages

  1. Event capture phase
  2. Target stage
  3. Event bubbling phase

The best way to understand this process is to read the picture. The arrows in the picture below represent the "shuttle" path of time.

This process is very similar to when everyone was playing on a trampoline when they were young: falling from a height, hitting the trampoline and then bouncing and returning to the height, the whole process takes a symmetrical "V" shape

When an event is triggered, it first undergoes a capture process: the event "shuttles" from the outermost element, and "shuttles" layer by layer to the innermost element. This shuttle process will continue until the event reaches its target element (that is, the element that actually triggered the event). At this point, the event flow is switched to the "target stage"-the event is received by the target element. Then the event will be "rebounded" and enter the bubbling phase-it will "upstream" along the path it came from, and walk back layer by layer.

Event object basics

When the event shuttles through the layers of DOM elements, it is not idle-wherever it goes, it will trigger the event handler installed on the current element. For example, you clicked the button node in the image above, but in fact, the click event handler is also installed on the div node. Then when the click event triggered by the button node passes through the div node, the processing function on the div node will still be triggered.

When the DOM receives an event and the corresponding event processing function is triggered, an event object event is generated as an input parameter of the processing function. This object contains information related to the event, such as which element triggered the event, the type of event, and so on.

Now let s write a simple HTML

<!DOCTYPE html > < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < meta http-equiv = "X-UA-Compatible" content = "ie=edge" > < title > Document </title > </head > < body > < div class = "outer" > < button id = "button" > Click me </button > </div > </body > </html > Copy code

We want to see what the click event object of the button in this demo looks like, we can write the corresponding processing function like this

function clickProcessor ( event ) { console .log(event) } Copy code

Now when we trigger a mouse click, the corresponding event object looks like this

We can see that in addition to the basic information that an event generally has, it also includes some supplementary information unique to a certain type of event (for example, for a click event, the mouse position-related information is recorded here). This event object is very interesting, and we will focus on analyzing it next.

Sorting out test sites for event objects

In the event object, there are some properties and methods, which are especially commonly used by us. This part is relatively fragmented, but the frequency of investigation is higher. The interviewer sometimes asks you individually, but more often they tend to directly see if you can use them to write code in coding questions. We summarize this part of the test sites as follows

  1. currentTarget

It records which element the event is currently being received by, that is, "which element is passing by". This element is always changing, because the spread of events is a process of shuttles.

If the element bound by the event handler is the same as the specific trigger element, then the three values of this , event.currentTarget , and event.target in the function are the same . We can use this as a basis to determine whether the current element is the target element .

  1. target

Refers to the specific target that triggered the event, that is, the most specific element, which is the true source of the event.

Even if the event handler is not bound to the target element, but is bound to the parent element of the target element, as long as it is triggered by the internal target element bubbling to the parent container, then we can still perceive through the target The target element is the true source of the event.

  1. preventDefault prevents the default behavior

This method is used to prevent the default behavior of specific events, such as the jump of a tag.

e.preventDefault();

  1. stopPropagation no longer dispatches events

This method is used to terminate the further propagation of the event during the capture, target processing or bubbling phase of the propagation process. After calling this method, the handler on the node that handles the event will be called, and the event will no longer be dispatched to other nodes.

e.stopPropagation();

Sometimes we don't want the triggering of an event to bring about the effect of "one stone stirs up waves", and we hope to control its influence within the scope of the target element. In this case, don't forget stopPropagation.

  1. Event objects can be created manually

The event object does not necessarily need you to trigger a specific event to make it "naturally", it can also be created manually: We can use the Event() constructor to create a new event object Event.

event = new Event(typeArg, eventInit);

html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> #divA, #divB, #divC { width: 100px; height:100px; } #divA { background-color: #333; } #divB { background-color: #dd5990; } #divC { background-color: #ccc990; } </style> </head> <body> <div id="divA"> A</div> <div id="divB"> B</div> <div id="divC"> C</div> </body> </html>

divA addEventListener

var divA = document.getElementById('divA') document.addEventListener('click',function(){ console.log(' A') })

A B C A B C

A B C

A B C A

The first thing you need to understand is the creation of custom events. For example, if we want to create a "clickA" event that does not exist, to indicate that A is clicked, we can write this

var clickAEvent = new Event( 'clickA' ); Copy code

OK, now the event is there, let's complete the monitoring and dispatch of the event

//Get divB element var divB = document .getElementById( 'divB' ) //divB listens to clickA event divB.addEventListener( 'clickA' , function ( e ) { console .log( 'I am little B, I feel little A ' ) console .log(e.target) }) //Get the divC element var divC = document .getElementById( 'divC' ) //divC listens to the clickA event divC.addEventListener( 'clickA' , function ( e ) { console .log( 'I am a little C, I feel little A ' ) console .log(e.target) }) //The listener function of the A element must also be modified under divA.addEventListener( 'click' , function () { console .log( 'I am Little A' ) //Pay attention to the dispatch action here, that is, we dispatch the event ourselves divB.dispatchEvent(clickAEvent) divC.dispatchEvent(clickAEvent) }) Copy code

We can see the following output

It shows that our custom event has taken effect!

However, you may have noticed that here we must get the exact elements such as divC and divA to install and distribute events. Sometimes, in order to further decouple, we will also consider putting all the monitoring functions on the document element, which will take different actions according to different types of custom events. This kind of thinking is very similar to the event agent .

Event agent

Earlier we talked about custom events, mainly because we were afraid that everyone would fall into the pit. What do you mean? In fact, I personally rarely examine candidate custom events. In my opinion, I assume that as long as your js foundation is good enough, this question must be fine (js foundation can be examined in other ways). However, for some interviewers who have a strong feeling of native js, especially those who have written all the way from the front-end prehistoric period and become a Team Leader, the less the code is written and the less able to keep up with the trend, custom events can explain Many questions (after all, he wrote a lot in his early years). Let's take precautions, whether he wants to take the exam or not, just learn it first.

The frequency of interviews for custom events varies from interviewer to interviewer. The event agency is a proper high-frequency test site. If you fall into my hands, I have to ask you; if you fall into my colleague's hands, my colleague has to ask you too. Many students find it too basic and think it is a question for fresh graduates. This idea is half right-it is indeed the basics, but the basic investigation is not divided into groups. So, the event agent has to work hard to learn! (Knocking on the blackboard)

Event delegation is also called event delegation. If you haven't understood what this stuff is before, don't rush to search for concepts now. This thing is not suitable for the concept as soon as it comes up, let s do the problem directly

Real question: In the following HTML, I hope to click on each li element to output its inner text content. what will you do?

<!DOCTYPE html > < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < meta http-equiv = "X-UA-Compatible" content = "ie=edge" > < title > Document </title > </head > < body > < UL ID = "POEM" > < Li > goose goose </Li > < Li > Qu to Tiange </Li > < Li > white hair floating green </Li > < Li > Anthurium dial Shiba </li > < li > It s noon on the day of hoeing the wheat </li > < li > Sweat dripping under the soil </li > < li > Who knows Chinese food </li > < li> A Journey </li > < li > back no more </li > < li > I did not move back </li > </ul > </body > </HTML > Copy the code

A more intuitive idea is to let every li element listen to a click action

<script> //Get the li list var liList = document .getElementsByTagName( 'li' ) //Install the monitoring functions one by one for ( var i = 0 ; i <liList.length; i++) { liList[i].addEventListener( 'click' , function ( e ) { console .log(e.target.innerHTML) }) } </script> Copy code

If you really do that, you won't get a point for this question. Remember, once you encounter a problem that meets the following three characteristics in the DOM series of interview questions

  1. You need to install a listener function that listens to a certain event (the event is the same)
  2. The monitoring function is installed on a series of elements with the same characteristics (the element characteristics are the same, generally speaking, they have the same parent element)
  3. This series of monitoring functions on the same feature elements still do the same thing (the monitoring logic is the same/the same)

At this time, you must have these four big words in your mind-event agent!

What's going on? Upstairs, we installed 10 monitoring functions for 10 li. Are you tired? Is it expensive? Think about it carefully. The 10 monitoring functions all do the same thing. Can we converge this logic to one element? The answer is yes, why can it? Because of events bubbling up! Do you think that if you click on any li, the click event will be sent to their common daddy-the ul element? Then can I let ul do this? The answer is yes, because ul can not only perceive the incident that comes up, it can also get the element that actually triggered the event through e.target, so as to achieve a seamless proxy.

var ul = document .getElementById( 'poem' ) ul.addEventListener( 'click' , function ( e ) { console .log(e.target.innerHTML) }) Copy code

Keep in mind that e.target refers to the specific target that triggered the event, and it records the source of the event. So, no matter where our monitoring function is executed, as long as I get this e.target, it is equivalent to the element that actually triggered the event. After getting this element, we can fully simulate its behavior and achieve undifferentiated monitoring effects.

Using the bubbling feature of events like this, the same type of monitoring logic of multiple child elements is merged into the parent element through a monitoring function to manage the behavior, which is the event proxy. Through event proxy, we can reduce memory overhead, simplify registration steps, and greatly improve development efficiency.