preface

Event bubbling, event capture, event delegation, and event binding are arguably the most important aspects of JavaScript fundamentals

Company: Tencent


The DOM event flow

The event flow describes the order in which events are received from the page.

When events occur, they are propagated in a specific order between element nodes, which is called the DOM event stream.

There are three stages:

  1. Event capture phase
  2. In the target stage
  3. Event bubbling phase

As we know, IN the DOM model, HTML is multi-layered, and when an event is generated on an HTML element, the event is propagated in a specific order between element nodes in the DOM tree. Each node in the propagation path receives this event, which is the DOM event stream. When an event occurs, it is propagated from the inside out. Because the event stream itself has no ability to process events, functions that process events are not bound to the event source. For example, if we click a button and generate a click event, the click event will start propagating up into the code that handles the event.

Event capture: Events fire from the least precise object (the Document object) to the most precise (events can also be captured at the window level, though they must be specified by the developer).

Event target: When the target element is reached, the corresponding handler for the event of the target element is executed. If no listener function is bound, it is not executed.

Event bubbling: Events are emitted from the most specific event target to the least specific event target (the Document object). When an element receives an event, it passes the event to its parent, all the way to the Window.

Note:

  • The JS code can only capture or bubble one of the phases
  • Onclick and attachEvent only get the bubbling phase
  • AddEventListener (type, listener[, useCapture]) the third argument, if true, calls the event handler during the event capture phase; If it is false (the default is false if you do not write), it indicates the eventBubbling phaseElectrophoresis event handler.
  • In real development, we rarely use event capture (older versions of IE are not compatible) and focus more on event bubbling
  • Some events are not bubbling, likeOnblur, onFocus, onMouseOver, onmouseleave
  • While bubbling can sometimes cause trouble, it can also do clever things, as we’ll explain later

The event object

  • Event is an event object, written inside the parentheses of our listener function, as a parameter
  • The event object only has the event, it is automatically created by the system for us, we do not need to pass parameters
  • An event object is a collection of data related to our events, such as mouse clicks that contain information related to the mouse
  • The event object can be named by ourselves, such as Event, EVT, e, etc
  • Event objects also have compatibility issues. IE 6, 7, and 8 are implemented through window.event

Compatibility writing:

event = event || windoe.event;
Copy the code

Event object common properties and methods

Event object property method instructions
e.target Returns the object that triggered the eventstandard
e.scrElement Return triggered events for objects that are not standard IE 6, 7, 8 use
e.type Return the type of the event, such as click, mouseover, and so on, without on
e.cancelBubble This property prevents bubbling, non-standard, IE 6, 7, 8 use
e.returnValue This property prevents default events (default behavior) from being non-standard, as IE 6, 7, 8 use, such as not allowing links to jump
e.preventDefaule() This method prevents default event (default behavior) standards, such as not allowing links to jump
e.stopPropagation() Prevent bubbling, standard

The difference between e.target and this

This returns the object (element) to which the event is bound

E.target returns the clicked object, that is, who triggered the event, such as click event -> who was clicked

var ul = document.querySelector('ul');
ul.addEventListener('click'.function (e) {
    console.log(this);
    console.log(e.target);
})

// 
      
    ...
// <li>123</li> Copy the code

Prevent object default behavior (heavy)

Three ways:

  • e.preventDefaule();Is a method suitable for ordinary browsers
  • e.returnValue; Is a property for IE 6, 7, and 8
  • return false; There is no compatibility problem, but note that the following statement is not executed, directly jump out

Prevent bubbling (heavy)

  • event.stopPropagation(); // Normal browsers stop bubbling
  • event.cancelBubble; // IE 6 7 8 stops bubbling
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', alertName, false);
son.addEventListener('click', alertName, false);
document.addEventListener('click'.function () {
    alert('document');
}, false);
function alertName (event) {
    alert(this.getAttribute("class"));
    event.stopPropagation();    // Stop bubbling
    event.cancelBubble;         // IE 6 7 8 stops bubbling
}
Copy the code

Event delegate (proxy, delegate)

Principle of Event Delegation (heavy)

The idea behind event delegation is that instead of setting event listeners on each child node, you set event listeners on its parent node and then set each child node using the bubbling principle.

For example, register a click event for UL, use the target of the event object to find the current hit li, and then the event bubbles to UL. Ul has a registration event, which triggers the event listener.

The role of event delegation

The DOM is manipulated only once, improving the performance of the program.

Why event delegate? (heavy)

In JavaScript, the number of event handlers added to the page is directly related to the overall performance of the page, because the dom is constantly manipulated, the more likely the browser is to redraw and reflow, and the longer the page interaction events are, which is why dom manipulation is minimized. Each event handler is an object, so one more event handler will take up more space in memory. If you want to use the event delegate, will put all the operations in the JS program, only to its parent (if there is only one parent) this object operation, and dom operation only need to interact once, so that can greatly reduce the number of interactions with DOM, improve performance;

Small case of event delegation

Requirement: When the mouse is placed over li, the background color of li turns gray

<ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>
Copy the code

Common implementation

Bind an event to each li to make it gray:

$("li").on("mouseover".function(){$(this).css("background-color"."gray").siblings().css("background-color"."white");
})
Copy the code

This common implementation seems fine, but if we dynamically add a new LI to ul after this code is over, the new LI will have no event, and our DOM will be overwhelmed if there are countless Li nodes.

Implementation using event delegate

Js events are bubbling, so this can change, but event.target does not. It is always the target DOM element that receives the event directly

Using event bubbling, you can control all li events under UL by specifying only UL event handling

$("ul").on("mouseover".function(e) {
    $(e.target).css("background-color"."gray").siblings().css("background-color"."white");
})
Copy the code
  • Step 1: Bind events to the parent element

    Add a binding event to the ul element, bind the mouseover event to the CSS (you can also add a binding for click via addEventListener)

  • Step 2: Listen for bubbling events on child elements

    The default is bubbles, so if you click on the child li, it bubbles up

  • Step 3: Find which child element is the event

    The event object is received with the parameter E of the anonymous callback function, and the target that triggered the event is obtained with target (the type of target can be determined by determining what kind of child object executes the event).