JavaScript 创建自定义事件
除了让用户与浏览器交互触发生成事件,还可以使用 JavaScript 生成事件,而且还可以自定义事件的类型(不仅仅是浏览器内建事件类型。
事件构造器
内建事件类形成一个层次结构 hierarchy,类似于 DOM 节点类,其根是内建的 Event 类,还有一些具有特殊属性的内建事件类,如 UIEvent
、FocusEvent
、MouseEvent
、WheelEvent
、KeyboardEvent
等,通过这些类(事件构造器)可以构建新的事件对象
let event = new Event(type[, options]);
Announce
参数说明
- type 事件类型,字符串形式,如点击事件类型
"click"
的字符串,也可以是自定义"my-event"
的参数 - options 具有两个可选属性的对象,默认情况下两者都为
false
即{bubbles: false, cancelable: false}
bubbles: true/false
如果为true
,那么事件会冒泡cancelable: true/false
如果为true
,那么“默认行为”就会被阻止。稍后我们会看到对于自定义事件,它意味着什么。
Tip
对于内建的 UI 事件 有相应构造器创建相应类型的事件,推荐使用这些构造器创建事件对象,因为它们允许添加指定标准属性(而使用通用的 Event
构造器是不允许添加额外的信息的)。
// 创建一个 MouseEvent 鼠标交互事件
let event = new MouseEvent("click", {
bubbles: true,
cancelable: true,
clientX: 100, // 允许设置鼠标指针在点击元素(DOM)中的X坐标
clientY: 100 // 允许设置鼠标指针在点击元素(DOM)中的Y坐标
});
alert(event.clientX); // 100
分配事件
事件对象被创建后应该使用 elem.dispatchEvent(event)
在特性的元素上「运行」它,然后处理程序会对它做出反应,就好像它是一个常规的(由用户交互触发的)浏览器事件一样。
<button id="elem" onclick="alert('Click!');">Autoclick</button>
<script>
// 创建事件对象
let event = new Event("click");
// 分配事件,类似于程序自动模拟触发了 click 事件的发生
elem.dispatchEvent(event);
</script>
Tip
可以使用事件对象属性 event.isTrusted
判断事件是否由自真实用户操作触发的,如果属性为 true
表示事件由用户触发;如果属性为 false
表示事件由脚本生成。
自定义事件
可以使用通用事件 Event
构造器创建事件对象,但推荐使用构造器 new CustomEvent
创建自定义事件,该事件类明确地「标注」了创建的事件类型为自定义事件。
从技术上讲 CustomEvent 和 Event
一样,但它提供了第二个参数(对象类型),具有特殊的 detail 字段/属性以传递任何自定义的信息,我们可以通过 event.detail
来访问这些信息。
<h1 id="elem">Hello for John!</h1>
<script>
// 事件附带给处理程序的其他详细信息
elem.addEventListener("hello", function(event) {
alert(event.detail.name);
});
elem.dispatchEvent(new CustomEvent("hello", {
detail: { name: "John" }
}));
</script>
Warning
当我们需要为自定义事件设置监听器时,应该使用方法 elem。addEventListener
,因为 on<event>
仅存在于内建事件中,如 document.onhello
是无法运行的。
event.preventDefault
对于自定义的事件没有默认的浏览器行为,但是此类事件的代码可能有自己的计划,即触发该事件之后会执行相应的操作,类似于内建事件,自定义事件也可以调用方法 event.preventDefault()
向系统发出一个信号,如果调用了该方法分配方法 elem.dispatchEvent(event)
就会返回 false
,可以基于该信号进行条件判断以取消相应的行为。
<pre id="rabbit">
|\ /|
\|_|/
/. .\
=\_Y_/=
{>o<}
</pre>
<!-- 监听 button 元素上的 click 事件,并触发 hide 处理程序 -->
<button onclick="hide()">Hide()</button>
<script>
// button 点击事件的处理程序 hide
function hide() {
// 创建一个自定义名称为 hide 的事件
let event = new CustomEvent("hide", {
cancelable: true // 没有这个标志,preventDefault 将不起作用
});
//将 hide 事件分配给 rabbit 元素,并基于事件是否被阻止,返回 true/false
if (!rabbit.dispatchEvent(event)) {
alert('The action was prevented by a handler');
} else {
rabbit.hidden = true;
}
}
// 在 rabbit 元素上监听 hide 事件
rabbit.addEventListener('hide', function(event) {
// hide 事件触发的处理程序,询问用户是否阻止「默认」行为
if (confirm("Call preventDefault?")) {
event.preventDefault();
}
});
</script>
上述代码实例演示了基于用户控制决定是否隐藏的兔子(字符串)的过程,我们在该元素上分派了 "hide"
事件,并在该元素上监听该事件,基于用户的选择决定是否使用 event.preventDefault()
来取消隐藏行为。