preface

What do you think of when you think of Javascript events? I think there are words like event capture, bubble, agent in the answer.

But is it really understood?

Javascript itself, as an event-driven language, shows the importance of events.

If a user clicks a button on a web page, you might want to respond to that action by displaying a message box. This is an event.

Here is the article map:

Again, it’s customary to start with a question:

  1. Can you tell me what you know about the mechanism of events?
  2. Catch bubbles. Describe them briefly. Okay?
  3. Can you talk about event flow?
  4. Can you talk about the event agent?
  5. AddEventListener (), what are the three parameters? The third parameter default value, default behavior?
  6. Only one specified child component is required to capture the event. How do I do that? How do I block the default behavior?
  7. How does JavaScript bind listener functions to events?
  8. What are the concerns with event delegation? How to solve it?
  9. What if different child elements require different events?
  10. What do you notice when using removeEventListener()?

Hope you will, or after reading the article you will 😄

(Since the following examples will cover some information about listening events and event objects, they will be introduced first.)

I. Event monitoring

In the browser, the event model reacts to events by listening to functions. After the event occurs, the browser listens for the event and executes the corresponding listener function, event-driven programming mode

There are three ways to bind listener functions to events in javascript:

1.1 Event handler Properties

Here’s an example:

chestnuts1:window.onload = doSomething;// Notice doSomething herechestnuts2: div. The onclick =function(event) {
    console.log('Trigger event');
  };
Copy the code

The onload, onclick is the event handler property used in this scenario, just like any other property, but with one special twist – when you assign some code to it, the code will run as soon as the event triggers (like chestnut 2).

1.2 inline event handlers

Here’s an example:

<button onclick="doSomething()">Press me</button> // Note doSomething() hereCopy the code

The “doSomething()” attribute value is actually the JavaScript code to run when the event occurs. You can also write javascript code directly into it (but mixing HTML and javascript makes the document difficult to parse, which is bad).

1.3 the addEventListener () and removeEventListener ()

“Dom2-level events” defines two methods for handling operations that specify mixed deletion event handlers: addEventListener() and removeEventListener(), both of which are contained in all nodes and take three parameters:

  1. Name of the event to process
  2. Function as an event handler
  3. A Boolean value (true: the capture phase calls the function; False: call function during bubble phase)
  • The same listener addEventListener registers multiple processors (handler,handler1)

When we try to register multiple handlers using the event handler property method above:

 var btn = document.getElementById("myBtn");
  var handler = function() {
    console.log("I'm handled by handler().");
  }
  var handler1 = function() {
    console.log("I'm handling handler1()");
  }
  btn.onclick = handler;
  btn.onclick = handler1;
Copy the code

Only one result is printed because any subsequent properties set will attempt to override the earlier properties, use addEventListener to resolve this issue:

 var btn = document.getElementById("myBtn");
  var handler = function() {
    console.log("I'm handled by handler().");
  }
  var handler1 = function() {
    console.log("I'm handling handler1()");
  }
  btn.addEventListener("click",handler,false);
  btn.addEventListener("click",handler1,false);
Copy the code

  • The use of the removeEventListener ()

With addEventListener(), removeEventListener() is used to remove, and note that the parameters passed are the same as those used to add the handler.

Correct: btn.addeventListener ("click",handler,false);
btn.removeEventListener("click",handler,false); Error: btn.addeventListener ("click",handler,false);
btn.removeEventListener("click",handler1,false);
Copy the code

And anonymous functions don’t work either

 btn.addEventListener("click".function() {
    console.log(1)},false);
 btn.removeEventListener("click".function() {
    console.log(2)},false);
Copy the code

2. Event object

When an Event is triggered in the DOM, an Event object will be generated, which contains all the information related to the Event, including the element causing the Event, the type of the Event, and other information related to the specific Event.

And the Event object itself is a constructor that can be used to generate instances.

event = new Event(type, options);
Copy the code

That, as a constructor, has its own set of properties and methods, so let’s expand around that.

2.1 attributes

  • bubblesIndicates whether the Event bubbles (events generated by the Event constructor, by default, do not bubble)
  • targetThe target node of the event can be returned, and the target can be represented as the DOM of the current event operation
  • eventPhaseStage of invoking the event handler:

1 — represents the capture phase

2 — Means “on target”

3 — represents the bubbling stage

<body>
  <button id="myBtn">button</button>
</body>
<script>
  var btn = document.getElementById("myBtn");
  btn.onclick = function(event) {
    console.log(event.eventPhase,"btn.onclick");
  }
  document.body.addEventListener("click".function(event) {
    console.log(event.eventPhase,"document.body.addEventListener")},true)
  document.body.onclick = function(event) {
    console.log(event.eventPhase,"document.body.onclick");
  }
Copy the code

  • cancelableWhether to cancel the default behavior of the event
  • defaultPreventedTrue means preventDefault() has been called
  • currentTargetThe element of time that the event handler is handling
  • target Object of the event

CurrentTarget (); currentTarget ();

Inside the event handler, the object this is always equal to currentTarget, while target contains only the instance target of the event. When the target element is specified directly — btn.onclick in the following example — this, currentTarget, and target contain the same value.

 var btn = document.getElementById("myBtn");
  btn.onclick = function(event) {
    console.log(event.currentTarget == this); //true
    console.log(event.target == this); //true
  }
Copy the code

If you do not specify the target element directly:

Event.currenttarget, this, points to document.body, while Event.target points to Document.getelementById (“myBtn”), because it is the target of the Click event.

Because there is no event handler registered on the button, the click event bubbles up to Document.body, where the event is handled.

 var btn = document.getElementById("myBtn");
  document.body.onclick = function(event) {
    console.log(event.currentTarget === document.body);
    console.log(this= = =document.body);
    console.log(event.target === document.getElementById("myBtn"));

  }
Copy the code

2.2 methods

  • Event.preventDefault()The default behavior for cancelling events, used with cancelable to true
  • Event.stopPropagation()Cancel further capture or bubbling of events, used with bubbles being true
  • Event.composedPath()Returns an array of the lowest node of the event and all the upper nodes that bubble past in sequence.
  • Event.stopImmediatePropagation() Cancels further capture or bubbling of events while preventing any event handlers from being called. (Sort of like an upgraded version of stopPropagation())

3. Event mechanism

3.1 Event Bubbling

Events are initially received by a specific element (the node with the deepest nesting level in the document) and then propagated up the hierarchy to less specific nodes.

<! DOCTYPE html><html lang="en">
<head>
  <title>Document</title>
</head>
<body>
  <div id="myDiv">button</div>
</body>
</html>
Copy the code

If you click in the page

Element, then the click event is propagated in the following order:

graph TD
Element-div --> Element-body --> Element-html --> Document

The Click event is first sent on the div element where we clicked, and then propagated up the DOM tree (I didn’t draw it very well, it should have) at every level of the node, all the way up to the Document object.

3.2 Event Capture

Event capture is where less specific nodes receive the event earlier, while specific nodes should receive the event last, capturing it before taking the time to reach the intended destination.

<! DOCTYPEhtml>
<html lang="en">
<head>
  <title>Document</title>
</head>
<body>
  <div id="myDiv">button</div>
</body>
</html>
Copy the code

If you click in the page

Element, then the click event is propagated in the following order:

graph TD
Document --> Element-html --> Element-body --> Element-div

In event capture, the Document object receives the Click event and then moves down the DOM tree to the actual target of the event.

Iv. Event Flow (Event Propagation)

When an event occurs, it propagates between parent and child elements. This propagation, also known as event flow, is divided into three stages:

  1. Conduction from the Window object to the target node is called the capture phase
  2. Triggered at the target node, called the “target phase”
  3. Return the Window object from the target node, called the “bubbling phase”

(Arrow below, capture down and bubble up)

graph TD
Document --> Element-html --> Element-body --> Element-div --> Element-body --> Element-html --> Document

Combine the property approach above with a known conceptual understanding of bubble capture and consider the following example:

<body>
  <div>
    <p>Click on the</p>
  </div>
</body>

<script>
  var phases = {
  1: 'capture'.2: 'target'.3: 'bubble'
};

var div = document.querySelector('div');
var p = document.querySelector('p');

div.addEventListener('click', callback, true); // Call callback when captured
p.addEventListener('click', callback, true); // Call callback when captured
div.addEventListener('click', callback, false); // Call callback when bubbles
p.addEventListener('click', callback, false); // Call callback when bubbles

function callback(event) {
  var tag = event.currentTarget.tagName; // Specify the target tag name div p
  var phase = phases[event.eventPhase]; // Call the event handler stage
  console.log("Tag: '" + tag + "'. EventPhase: '" + phase + "'");
}
</script>
Copy the code

Analyze:

  1. From the results printed on the console above, you can see that the click event was triggered four times:
    The capture stage and bubble stage of the node are once each.

    The target phase of the node fires twice.

  2. The three stages

Note:

In the capture stage, they are window, Document, HTML, body, div and P.

In the bubbling stage, they are P, div, body, HTML, document and window.

(I just drew div and P below)

  • Capture phase: The DIV click event is triggered
graph TD
Element-div --> Element-p 
  • Target stage:

The event reaches P, triggering the click event for P

  • Bubble phase: Trigger div click event again
graph TD
Element-p --> Element-div
  1. Monitoring function
p.addEventListener('click', callback, true);
p.addEventListener('click', callback, false);
Copy the code

There is a listener function on the p node, and they all fire because of the click event, so there are two outputs in the target phase

V. Event delegation (Event agent)

In javascript, the time handlers added to the page are directly related to the overall performance of the page, and the solution to the “event handler overload” problem is the event delegate, also known as the event proxy.

(Hopefully, you’ve read, or understood, the previous part of the article, which is useful for understanding event delegation.)

5.1 a preliminary

Well, let’s start with an example that compares not using event delegation with using event delegation:

<ul id="link">
    <li>1</li>
</ul>
Copy the code

Implement click li, trigger the event handler

Case without event delegate:

It is possible to define events directly on the li tag, but this operation requires finding the UL tag, iterating through the tags (ul1.getelementsByTagName (‘li’) is an array), and then clicking on li to find the location of the target Li. And you have to look for the LI tag repeatedly every time.

 var ul1 = document.getElementById('link');
    var li1 = ul1.getElementsByTagName('li');

    for(var i=0; i<li1.length; i++){ li1[i].addEventListener("click".function() {
        console.log("Add an event handler to the li element.")})}Copy the code

Using event delegate:

    var ul1 = document.getElementById('link');
    var li1 = ul1.getElementsByTagName('li');

    ul1.addEventListener("click".function() {
        console.log("Add event handler to ul element")})Copy the code

We’re using the parent ul for event handling, and when LI is clicked, because of the bubbling principle, the event will bubble to UL, because UL has a click event, so the event will be triggered

But there is a small problem here, even when I click on ul, there is a trigger event. How can I only trigger when I click on LI, but not when I click on ul?

5.2 perfect

In this code, we use the event delegate to add listening events only for the UL element. Since Li is a child node of the element and its events bubble up, the click event will eventually be handled by this function.

We know that the event target is the list item that was clicked, and event.target refers to the list item that was clicked.

 var ul1 = document.getElementById('link');
    // var li1 = ul1.getElementsByTagName('li');ul1.addEventListener("click".function(event){var event = event || window.event;vartarget = event.target;if(target.nodeName.toLowerCase() == 'li') {console.log(123);console.log(target.innerHTML); }})Copy the code

5.3 upgrade

This is a list item, what if I need to add three different events for three Li’s? :

 <ul id="myLinks">
    <li id="jingda1">jingda1</li>
    <li id="jingda2">jingda2</li>
    <li id="jingda3">jingda3</li>
  </ul>
Copy the code
  • Without event delegation:
<script>

  var item1 = document.getElementById('jingda1')
  var item2 = document.getElementById('jingda2')
  var item3 = document.getElementById('jingda3')
  
  item1.addEventListener("click".function() {
    console.log(1)
  })
  item2.addEventListener("click".function() {
    console.log(2)
  })
  item3.addEventListener("click".function() {
    console.log(3)
  })
</script>
Copy the code
  • Using event Delegate
var ul1 = document.getElementById('myLinks'); ul1.addEventListener("click".function(event){var event = event || window.event;var target = event.target;
        // console.log(target.id)

      switch(target.id) {
        case 'jingda1':
          console.log("jingda1");
          break;
        case 'jingda2':
          console.log("jingda2");
          break;
        case 'jingda3':
          console.log("jingda3");
          break;
      }
Copy the code

The event target is the list item that was clicked, and the event. Target refers to the list item that was clicked, and the appropriate action is determined by detecting the target.id attribute.

conclusion

So much for javascript event-related knowledge, there are a lot of things that may not be covered. Or there is a wrong place, hope a lot of advice

(There is another big category that I haven’t summarized -javascript event types. I hope you can sort it out if you have time. I still want to focus on the event mechanism in this article.)

On the topic of javascript events, you probably don’t use them that much, but it’s important to know. For example, when learning react knowledge, setSate is asynchronous or synchronous, there will be synthesized events in the middle. To understand this, you must first understand javascript’s event mechanism. This seems to be another little blind spot, bald head.

Well, hopefully by the end of this article you’ve learned a little bit more about javascript events. There may be a lot of questions, and finally I recommend a few books and articles that I am studying and referring to the relevant knowledge points.

I am Jingda, a junior. I hope to learn and make progress together with you. 🙆 🙆 🙆

Come on!

The article must have written bad place, welcome the comment section to correct.

Write incomplete place, also suggest everyone to read the following reference ah 👇👇👇

[Reference article 💬]

Javascript Advanced Tutorial

Web API interface Reference -Event

Javascript Tutorial – Events

Js event delegate or event delegate details