Dispatching Custom Events
JavaScript Dispatching Custom Events (JavaScript调度自定义事件)
Custom events are used for generating graphical components. It can create not only completely new events, but also built-in events such as mousedown, click, and so on. It can be handy for automated testing. (自定义事件用于生成图形组件。它不仅可以创建全新的事件,还可以创建mousedown、click等内置事件。它可以方便地进行自动化测试。)
Event Constructor
Event Constructor (事件构造函数)
Built-in event classes are similar to DOM element classes: they set up a hierarchy. The built-in Event class is the root.
Event objects are generated in the following way:
let event = new Event(type[, options]);
Two arguments are distinguished: type and options. The type argument is the event type. The options argument is the object that has two optional properties such as:
bubbles: true/false: in case it’s true, the event will bubble.
cancelable: true/false: in case it’s true, then the default action can be prevented.
However, both of them are false ({bubbles: false, cancelable: false}) by default.
Dispatch Event
Dispatch Event (派遣活动)
Once an event object is generated, it should be run on an element applying the elem.dispatchEvent(event) call. (事件对象生成后,应在应用elem.dispatchEvent (event)调用的元素上运行。)
The handlers respond to it, as it was an ordinary browser event. If you have created the event using the bubbles flag, then it will bubble. (处理程序响应它,因为这是一个普通的浏览器事件。如果您使用气泡标志创建了事件,则它将冒泡。)
Let’s check out an example where the click event is created in JavaScript:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<button id="buttonId" onclick="alert('Clicked');">Autoclick</button>
<script>
let event = new Event("click");
buttonId.dispatchEvent(event);
</script>
</body>
</html>
Bubbling Example
Bubbling Example (冒泡示例)
A bubbling event can be created with the name “hello”. (可以创建名为“hello”的冒泡事件。)
First of all, it’s necessary to set bubbles to true, like this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<h1 id="elemId">Welcome to w3cdoc</h1>
<script>
// catch on document
(//catch on document)
document.addEventListener("hello", function(event) {
alert("Hello from " + event.target.tagName); // Hello from H1
});
// dispatch on elem
(//DISPATCH ON ELEM)
let event = new Event("hello", {
bubbles: true
});
elemId.dispatchEvent(event);
// the document handler activates and displays a message
(//文档处理程序激活并显示一条消息)
</script>
</body>
</html>
MouseEvent, KeyboardEvent and More
MouseEvent, KeyboardEvent and More (MouseEvent、KeyboardEvent等)
Let’s explore the shortlist of the classes for UI events:
UIEvent FocusEvent MouseEvent WheelEvent KeyboardEvent (UIEvent FocusEvent MouseEvent WheelEvent KeyboardEvent)
They can be used instead of new Event for creating such events. For example, new MouseEvent(“click”). (它们可以代替新事件用于创建此类事件。例如, new MouseEvent (“click”)。)
The correct constructor helps to indicate standard properties for such an event. For example, clientX/clientY for a mouse event:
let event = new MouseEvent("click", {
bubbles: true,
cancelable: true,
clientX: 200,
clientY: 200
});
console.log(event.clientX); // 200
Please, consider that the generic Event constructor doesn’t accept that. Here is what will happen if you try it:
let event = new Event("click", {
bubbles: true, // only bubbles and cancelable
cancelable: true, // work in Event constructor
clientX: 200,
clientY: 200
});
console.log(event.clientX); // undefined, unknown property is ignored
Custom Events
Custom Events (自定义事件)
Custom events are technically almost the same as Event. But, there is an exception. (从技术上讲,自定义事件与事件几乎相同。但是,有一个例外。)
Let’s start at an example where, in the second argument, an additional detail argument is added for custom information:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<h1 id="elemId">Welcome to w3cdoc</h1>
<script>
// add details come with event to the handler
(//将事件的详细信息添加到处理程序)
elemId.addEventListener("welcome", function(event) {
alert(event.detail.name);
});
elemId.dispatchEvent(new CustomEvent("welcome", {
detail: {
name: "w3cdoc"
}
}));
</script>
</body>
</html>
The detail property may include any data. (Detail属性可以包括任何数据。)
The CustomEvent provides specific detail field for it for avoiding conflicts with other event properties. (CustomEvent为其提供特定的详细信息字段,以避免与其他事件属性冲突。)
Events-in-events are Synchronous
Events-in-events are Synchronous (事件中的事件是同步的)
As a rule, events consider an asynchronous process. In other words, the browser processes onclick, and then a new event triggers. Then it waits till the onclick processing is over. (通常,事件会考虑异步进程。换句话说,浏览器处理onclick ,然后触发新事件。然后等待,直到onclick处理结束。)
But, there is an exception: when an event is initiated within another one. Afterward, the control passes to the nested event handler, then goes back.
Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<button id="menu">Click on button</button>
<script>
menu.onclick = function() {
alert("one"); // alert("nested")
menu.dispatchEvent(new CustomEvent("menuOpen", {
bubbles: true
}));
alert("two");
};
document.addEventListener('menuOpen', () => alert('nested'));
</script>
</body>
</html>
In the example above, the nested event menu menuOpen bubbles up, and then it is being handled on the document. The propagation and handling of the nested event should be completed before the processing returns from the outer code (onclick). It’s not only for dispatchEvent but for different other cases, too. Also, it is possible to place the dispatchEvent at the end of onclick or to wrap in setTimeout, like this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<button id="buttonId">Click on button</button>
<script>
buttonId.onclick = function() {
alert("one");
// alert(2)
(警报2)
setTimeout(() => buttonId.dispatchEvent(new CustomEvent("menuOpen", {
bubbles: true
})));
alert("two");
};
document.addEventListener('menuOpen', () => alert('nested'));
</script>
</body>
</html>
As you can see, dispatchEvent is executed asynchronously after the current code running is over. So, event handlers are completely separate. (如您所见, dispatchEvent在当前运行的代码结束后异步执行。因此,事件处理程序是完全独立的。)
The output sequence will be as follows:
one → two → nested
Summary
Summary (概要)
For generating an event from code, first of all, an event object should be created. (为了从代码生成事件,首先应该创建一个事件对象。)
The CustomEvent constructor is used for custom events. It includes an extra option, called detail, to which the event-specific data is assigned. Afterward, all the handlers will have access to it as event.detail . (CustomEvent构造函数用于自定义事件。它包括一个名为“详细信息”的额外选项,事件特定数据将分配给该选项。之后,所有处理程序都可以作为event.detail访问它。)
Custom events with their own names are, generally, created to meet architectural goals, for signaling what happens inside menus, carousels, sliders, and so on. (具有自己名称的自定义事件通常是为了满足架构目标而创建的,用于指示菜单、旋转木马、滑块等内部发生的事情。)