In the front-end development world, JavaScript and HTML often interact through events. Most of them are built-in events. This paper mainly introduces the concept and implementation of JS custom events, and analyzes the principle, function, application and precautions of custom events in detail by combining cases.

📚 1. What are custom events

In daily development, we are used to listening for many events on the page, such as click, mousemove, element out-of-focus, and so on. Event is a communication mode and a message in nature. It is possible to use event for communication only when there are multiple objects and modules. In multi-modular development, custom events can be used for inter-module communication. When some basic events do not satisfy our business, we can try custom events to solve the problem.

📚 2. Implementation method introduction

Currently, the two main ways to implement custom events are created by the JS native Event() constructor and CustomEvent() constructor.

1. Event()

The Event() constructor creates a new Event object, Event.

1.1 grammar

let myEvent = new Event(typeArg, eventInit);
Copy the code

1.2 parameter

TypeArg: DOMString, which indicates the name of the creation event. EventInit: Optional configuration items, including:

The field names instructions Whether or not an optional type The default value
bubbles Represents the eventWhether the bubbling. optional Boolean  false
cancelable Represents the eventCan it be cancelled?. optional Boolean  false
composed Indicates whether the event will be inShadow DOM outside the root nodeTrigger the listener. optional Boolean  false

1.3 Example

// Create a pingan event that supports bubbling and cannot be cancelled
let myEvent = new Event("pingan", {"bubbles":true."cancelable":false});
document.dispatchEvent(myEvent);

// Events can be fired at any element, not just document
testDOM.dispatchEvent(myEvent);
Copy the code

1.4 compatibility



Photo source:caniuse.com/

2. CustomEvent()

The CustomEvent() constructor creates a new event object, CustomEvent.

2.1 grammar

let myEvent = new CustomEvent(typeArg, eventInit);
Copy the code

2.2 parameter

TypeArg: DOMString, which indicates the name of the creation event. EventInit: Optional configuration items, including:

The field names instructions Whether or not an optional type The default value
detail Represents the data to be passed in the event, inEventListenerTo obtain. optional Any  null
bubbles Represents the eventWhether the bubbling. optional Boolean  false
cancelable Represents the eventCan it be cancelled?. optional Boolean  false

2.3 Example

// Create an event
let myEvent = new CustomEvent("pingan", {
  detail: { name: "wangpingan"}});// Add the appropriate event listener
window.addEventListener("pingan".e= > {
  alert(The pingan event is triggered. Yes${e.detail.name}The trigger. `);
});
document.getElementById("leo2").addEventListener(
  "click".function () {
    // Send events
    window.dispatchEvent(myEvent); })Copy the code





We can also add attributes to custom events:

myEvent.age = 18;
Copy the code

2.4 compatibility



Photo source:caniuse.com/

2.5 IE8 compatibility

The dispatchEvent event is used to send events, which is compatible with the fireEvent method in Internet Explorer 8 and later versions:

if(window.dispatchEvent) {  
    window.dispatchEvent(myEvent);
} else {
    window.fireEvent(myEvent);
}
Copy the code

3. Event() differs from CustomEvent()

From the parameters supported by both, you can see that Event() is suitable for creating simple custom events, while CustomEvent() supports custom events passed by parameters, which supports the detail parameter as the data to be passed in the Event and retrieved in EventListener.

Note: When an event is emitted, no callback is performed if the corresponding element and its parent element are not listening for the event. When you need to listen on child elements, you can host events on their parent elements so that events can be caught and executed by listeners during the event bubble phase. You can use event.target to get the element that triggered the event.

📚 3. Application scenarios

Event is essentially a message, and event pattern is essentially the realization of observer pattern, that is, where observer pattern can be used, event pattern can also be used.

1. Scenario Description

Here are two scenarios:

  • Scenario 1: A single target object changes and multiple observers need to be notified of the change.

For example, when you click “follow” in the list of micro-blogs, many things will happen at the same time: recommend more similar micro-blogs, increase the number of personal followers…

  • Scenario 2: Decouple multi-module collaboration.

For example, Xiao Wang is responsible for the development of module A, And Xiao Chen is responsible for the development of module B, which can only be implemented after the normal operation of module A.

2. Code implementation

2.1 Scenario 1 Implementation

Scenario 1: A single target object changes and multiple observers need to be notified of the change. This example simulates three pages for demonstration: 1. Weibo list page (Weibo. Js) 2. 3. Weibo Homepage (home.js)

In the ** Weibo list page (Weibo. Js) **, we import the other two pages and listen for the click event of [Follow Weibo] button. In the callback event, we create a custom event focusUser and send the defined event using dispatchEvent method on document.

// Weibo.js
import UserModule from "./User.js";
import HomeModule from "./Home.js";
const eventButton = document.getElementById("eventButton");
eventButton.addEventListener("click".event= > {
	const focusUser = new Event("focusUser");
  document.dispatchEvent(focusUser);
})
Copy the code

The code for the next two pages is basically the same. Here, for the convenience of observation, the two pages are set to output different logs.

// User.js
const eventButton = document.getElementById("eventButton");
document.addEventListener("focusUser".event= > {
    console.log("[fan list page] Listening for custom event trigger, event:",event);
})

// Home.js
const eventButton = document.getElementById("eventButton");
document.addEventListener("focusUser".event= > {
    console.log("[weibo homepage] Listening to the custom event trigger, event:",event);
})
Copy the code

After clicking “Follow Weibo” button, the console output the following log information:

Finally, in the ** Weibo list page (Weibo. Js), the ** component is responsible for distributing events, while the other groups are responsible for monitoring events. In this way, the coupling degree between the three components is very low, and they do not need to relate to each other and do not affect each other. This also implements the observer pattern.

2.2 Implementation of Scenario 2

Scenario 2: Decouple multi-module collaboration. For a more intuitive example, when weibo needs to add a new function of “one button, three connections”, the programmer can develop it only after the product prototype and UI design is completed. This example simulates four modules: 1. Flow control (index.js) 2. UI Design (design.js) 4. Programmer development (develop.js)

In the process control (index.js) module, we need to import the modules of the other three processes, and then listen for the “startTask” button click event. In the callback event, we create a custom event, startTask, And send defined events using the dispatchEvent method on the document.

// Index.js
import ProductionModule from "./Production.js";
import DesignModule from "./Design.js";
import DevelopModule from "./Develop.js";

const start = document.getElementById("start");
start.addEventListener("click".event= > {
    console.log("Start the mission.")
    const startTask = new Event("startTask");
    document.dispatchEvent(startTask);
})
Copy the code

In the Production product design module, after monitoring the task start event startTask, the prototype design was completed after 1 second simulation, and a new event productionSuccess was distributed to start the following UI draft design.

// Production.js
document.addEventListener("startTask".() = > {
    console.log("Product design begins...");
    setTimeout(() = > {
        console.log("Product prototype design completed.");
        console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -");
        document.dispatchEvent(new Event("productionSuccess"));
    }, 1000);
});
Copy the code

In UI draft design and program development module, actually similar, code implementation:

// Dedign.js
document.addEventListener("productionSuccess".() = > {
    console.log("UI draft design begins...");
    setTimeout(() = > {
        console.log("UI draft design completed");
        console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -");
        document.dispatchEvent(new Event("designSuccess"));
    }, 1000);
});

// Production.js
document.addEventListener("designSuccess".function (e) {
    console.log("Start developing features...");
    setTimeout(function () {
        console.log("[One key and three links] Development completed");
    }, 2000)});Copy the code

After the development, we click the “Start Task” button and see the console output the following log message:

Finally, the process control (index.js) module is responsible for distributing events, other components are responsible for monitoring events, according to the process to complete other tasks. As can be seen, prototype design, UI draft design and program development tasks, do not affect each other, easy to task expansion.

📚 4. Summary

This paper introduces the concept and implementation of JS custom events in detail, and combines two practical scenarios for code demonstration. If you are careful, you will notice that both scenarios are implemented using the Event() constructor. You can also use the CustomEvent constructor instead. In addition, this article also introduces the two implementation methods in detail, including their differences and compatibility. Finally, I hope you can think more about code decoupling and use custom events to improve code quality.

📚 5. Refer to the article

  • “Javascript Custom Event Function and Usage Case Analysis”
  • Event-MDN
  • CustomEvent-MDN