This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August

The event

Before we talk about the flow of events, let’s look at events.

The interaction between JavaScript and HTML is achieved through events. Events: Are specific moments of interaction that occur in a document or browser window. We can use listeners (or event handlers) to reserve events so that the appropriate code is executed when the event occurs. In plain English, certain behaviors occur when we perform certain actions (such as mouse clicks) on certain elements of a page. Like clicking a button and popping up a dialog box. This involves the button click event, which produces the action of popping up a dialog box.

Events first appeared in IE3 and Netscape Navigator2 as a way to share the load of server computing. When IE4 and Navigator4 were released, the two browsers offered similar but different apis

The event type

There are many types of events that can occur in a Web browser. Different event types have different event information. The FOLLOWING event types are specified in DOM3-level Events:

  • UI events that are triggered when a User interacts with elements on a page
  • Focus events, which are triggered when an element gains or loses focus
  • Mouse events that are triggered when the user performs an action on the page using the mouse
  • Wheel event that is triggered when a mouse wheel (or similar device) is used
  • A text event that fires when text is entered in a document
  • Keyboard events that are triggered when the user performs an action on the page using the keyboard
  • Synthesized event that is emitted when a character is entered for the IME (Input Method Edtor)
  • Mutation events, which are triggered when the underlying DOM structure changes

There are three ways to bind events:

  • Specify events directly on the DOM element, such as mouse click events:
<div onclick="Alert (' I'm click in the DOM element ')">Am I</div>
Copy the code
  • Get the element object in JavaScript and bind the event as an object attribute
<div id='clickMe'> Click on me </div> <script>var div = document.querySelector('#clickMe')
    div.onclick=function(){
        alert('I'm click')
    }
</scripit>
Copy the code
  • Events are bound through the event listener addEventListener()
<div id='clickMe'> Click on me </div> <script>var div = document.querySelector('#clickMe')
    // It is important to note here that binding events with event listeners does not have on
    div.addEventListener('click'.function(){
        alert('I'm click in the listener');
    })
</scripit>
Copy the code

Flow of events

The event flow describes the order in which events are received from the page. When an event occurs, it is propagated in a specific order between the element node and the root node, and all nodes along the path receive the event. This propagation process is called DOM event flow

Understanding the flow of events

Suppose we now have three concentric circles of div boxes on the page (as shown below), and then we bind a mouse click event to each circle. When we click on the innermost pink circle, the circle’s click event is triggered, and the event is propagated from the inside out until it stops at document. So the “I’m pink,” “I’m yellow,” and “I’m green” pop-ups will pop up, so if we bind the body, HTML, and document click events, the click events for those elements will also be triggered. This creates a stream of events.

There are actually three stages to the DOM event flow:

  • Event capture phase: The capture phase propagates from the outside in that is, from the root node to the innermost node, as opposed to our example above
  • Event target stage: The target stage is the stage when the event reaches the element on which we clicked, in this case the pink circle
  • Event bubble phase: The bubble phase is the same as in our case above, propagating from inside out until the end of the root node

So why is there a capture phase (outside-in) and a bubbling phase (in-out)? Does it go through the capture phase and the bubble phase every time an event is fired, resulting in an event being executed twice (obviously not)?

This is because both the IE and Netscape teams came up with the concept of event flow, but the two teams came up with event flow in completely opposite directions. IE’s event stream is a bubbling stream of events from the inside out, whereas Netscape’s capture stream is from the outside in. So there are two phases: capture flow and bubble flow. In fact, the code only executes once after we fire an event, because by default it only propagates through the event bubble stream, not the capture stream, so the code only executes once after the event is fired, and then bubbles up.

Event bubbling phase

IE’s stream of S events, called event bubbling, starts with the most specific element (the node with the deepest nesting in the document) being received and then propagates up the hierarchy to the less specific node (the document). Take the following code for example:

<! DOCTYPEhtml>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me></div>
</body>
</html>
Copy the code

If we click on a div element in the page, the click event is propagated in the following order:

  1. < div>
  2. < body>
  3. < html>
  4. document

That is, the Click event occurs first on the div element that we clicked on, and then propagates up the DOM tree at each level of the node until it reaches the Document object. The following figure shows the event bubbling process.

Event bubbling is supported by all browsers, but there are some differences in implementation. While event bubbles in IE5.5 and earlier skip HTML elements and go from body to document, IE9, Firefox, Chrome, and Safari bubble events all the way to the Window object.

Event capture phase

Another event flow that the Netscape team has come up with is called Event capturing. The idea of event capture is that less specific nodes should receive events earlier, while the most specific nodes should receive events last. The intent of event capture is to catch an event before it reaches the intended destination. Using the previous HTML code as an example, clicking on a div element triggers click events in the following order.

  1. documnet
  2. < html>
  3. < body>
  4. < div>

During event capture, the Document object first receives the Click event, which then propagates down the DOM tree until it reaches the actual target of the event, the DIV element. The following figure shows the event capture process

Although event capture is the only event flow model supported by Netscape, it is also currently supported by IE9, Safari, Chrome, Opera, and Firefox. Although the “DOM2-level events” specification requires that events should propagate from a Document object, these browsers propagate captured events from a Windows object. Few people use event capture because older browsers don’t support it. We can safely use event bubbling. Use event capture only for special needs.

Although the event capture flow model is now supported by the major browsers, as mentioned above, event propagation is done in the event bubble flow model by default. So what if we just want events to propagate in a capture flow model? At this point we must bind events in the form of an event listener (addEventListener), which takes three parameters: The first parameter is the type of event to bind, the second is the code to execute when the event is fired, and the third parameter is an optional Boolean parameter (false by default) that determines whether the event stream is propagated as captured or bubbled. True indicates that the captured stream mode is propagated, false indicates that the bubble stream mode is propagated, and the default false indicates that the bubble stream mode is propagated by default. Look at the following code:

<div id="clickMe"></div>
<script>
    var myDiv = document.querySelector("#clickMe");
    myDiv.addEventListener('click'.function(){
        console.log('I'll propagate in capture stream mode');
    },true);
</script>
Copy the code

In the code above we add a click event to the div and pass the third argument true, and the event stream propagates in capture stream mode.

In the target stage

As mentioned above, since the IE and Netscape teams came up with completely opposite concepts of event flow, it was not appropriate to use either of them, so a compromise was eventually adopted: In the three phases of the event flow, the event capture phase is passed first, then the actual target receives the event and is in the target phase, and finally the event bubble phase is passed, and finally the event flow ends. Here is a complete picture of the DOM event flow:

This raises another question, since both the capture phase and the bubble phase go through, doesn’t the same code execute twice when we fire an event? To address this issue, it was eventually specified that event propagation should be in event bubbling mode by default (IE wins). If you want to capture mode propagation you need to bind the event with a listener and set the third parameter to true using the method we described above.

To prevent a bubble

Whether events propagate in bubble mode or capture mode, one problem is that sometimes we don’t want events to propagate up or down, which means that the event stays on whichever element we fire. And that’s what we’re going to talk about next stop bubbling.

Event bubbling can be prevented from causing unnecessary errors and confusion. To stop bubbles, stopPropagation() is shown in the following code:

<div id="clickMe">ClickMe</div>
<script>
    var div = document.querySelector('#clickMe');
    div.addEventListener('click'.function(event){
        console.log('Event bubbling has been prevented');
        event.stopPropagation();
    });
</script>
Copy the code

In the above code, we can stop bubbling by calling event.stopPropagation() after receiving an event parameter in the event handler.

So that’s the DOM event flow.