「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」
前言
对于前端开发来说,接触的最多的一定是和 HTML 之间的时间交互,比方说 添加点击事件,添加拖拽事件,创建页面 dom 结点 等等。本文就将来讲述 JavaScript 中 自定义事件 的概念以及简单的定义方法,并且举出实际的例子来进行实践。
在你观看本文之前,最好对 发布订阅模式有所了解,因为事件的本质就是通过发布订阅的形式进行通信,如果不了解发布订阅的小伙伴可以先看一下我另一篇关于发布订阅的文章,对其先有一个大概的了解会更有利于你理解 自定义事件。
什么是 自定义事件
在我们日常的开发当中,会多次的使用到 dom 元素 提供给我们的事件,比如最常见的 点击事件(click),在元素上绑定上一个函数,当你点击函数的时候触发。
那你有没有去想过,为什么你点击了绑定点击事件的元素,会触发你定义的函数呢?
实际上,各种各种的绑定事件本质上都是页面提供给我们的监听事件,当我们使用 addEventListener 来绑定某一个事件的时候,就像是去监听这个事件,而当你触发了这个事件,那么就会发布这个事件,这时候你绑定的方法就会执行。
而浏览器提供给我们各种各样的事件,但是总会有不满足业务条件的情况,这时候我们就可以来定义 自定义事件,你可以自己定义它触发的结果,和如果去触发它,这完全可以由你自己决定,这可以用来解决很多开发中的问题。
简单的小例子
我们先来看一段简单的代码:
document.addEventListener("aa", () => {
console.log(1);
});
let myEvent = new Event("aa");
setTimeout(() => {
document.dispatchEvent(myEvent);
}, 1000);
它会在浏览器中等待一秒钟,然后输出 1
看到这里,可能熟悉发布订阅的人就会发现,这不就是一个发布订阅模式的实例吗,document.addEventListener 绑定事件相当于是绑定监听,代表着对哪一个事件感兴趣,document.dispatchEvent(myEvent) 相当于是发布事件,这时候对这个事件刚兴趣的就会运行它绑定的方法。
那么我们该怎么使用 自定义事件 呢,它里面的参数,我们又改如何去设定
自定义事件的实现方式介绍
目前实现 自定义事件 的方法主要有元素的 Event() 构造函数以及 CustomEvent() 构造函数 两种方式来创建
1. Event()
Event() 构造函数, 创建一个新的事件对象 Event。
语法
let myEvent = new Event(typeArg, eventInit);
参数
-
typeArg
是
DOMString类型,表示所创建事件的名称。简单的说就是一个String类型 - 字符串 -
eventInit 可配置对象,可选以下参数:
"bubbles",可选,Boolean类型,默认值为false,表示该事件是否冒泡。"cancelable",可选,Boolean类型,默认值为false, 表示该事件能否被取消。"composed",可选,Boolean类型,默认值为false,指示事件是否会在影子DOM根节点之外触发侦听器。
示例
MDN 文档中 -Event() - Web API 接口参考 | MDN (mozilla.org) 的例子中提到了一句话
// 创建一个支持冒泡且不能被取消的look事件
var ev = new Event("look", {"bubbles":true, "cancelable":false});
document.dispatchEvent(ev);
// 事件可以在任何元素触发,不仅仅是document
myDiv.dispatchEvent(ev);
事件可以被任何元素触发,但是例子并不是很充分,我们来自己测试一下:
let myDiv = document.createElement("div");
document.addEventListener("myTypeArg", () => {
console.log("document");
});
myDiv.addEventListener("myTypeArg", () => {
console.log("myDiv");
});
let myEvent = new Event("myTypeArg", { bubbles: true, cancelable: false });
setTimeout(() => {
document.dispatchEvent(myEvent);
}, 2000);
setTimeout(() => {
// 事件可以在任何元素触发,不仅仅是document
myDiv.dispatchEvent(myEvent);
}, 1000);
这样会在浏览器中先后输出 myDiv 和 document
可以看出实例化出来的同一个 myEvent 可以被多个事件绑定,这就是例子中 事件可以在任何元素触发,不仅仅是document 的实际使用。
cancelable 参数
主要是用于禁止或者允许 Event.preventDefault() 的事件取消,事件一旦被取消,接下去的发布就都不会执行。
2. CustomEvent()
构造方法 CustomerEvent() 创建一个新的 CustomEvent 对象。
语法
let myEvent = new CustomEvent(typeArg, customEventInit);
参数
-
typeArg
是
DOMString类型,表示所创建事件的名称。简单的说就是一个String类型 - 字符串 -
eventInit 可配置对象,可选以下参数:
-
detail,可选,Any类型,默认值为null,表示事件中需要被传递的数据,可以在EventListener中获取。 -
"bubbles",可选,Boolean类型,默认值为false,表示该事件是否冒泡。 -
"cancelable",可选,Boolean类型,默认值为false, 表示该事件能否被取消。
-
示例
let myDiv = document.createElement("div");
let myEvent = new CustomEvent("myTypeArg", {
detail: { msg: "hello world" },
bubbles: true,
cancelable: false,
});
myDiv.addEventListener("myTypeArg", (e) => {
console.log("myDiv", e.detail);
});
setTimeout(() => {
// 事件可以在任何元素触发,不仅仅是document
myDiv.dispatchEvent(myEvent);
}, 1000);
console.log(myEvent);
在 myEvent 中我们可以看到我们实例化时传入的参数,并且在监听的时候拿到参数
这也是 CustomEvent() 和 Event() 比较不同的地方,它有一个可以在实例化的时候传入的参数
应用
我们之前说过,自定义事件和发布订阅的思维是一样的,那么我们就可以在我们需要的页面,通过:
document.addEventListener(myEvent, fn);
来监听一个事件,然后在触发的时候调用:
document.dispatchEvent(myEvent);
来发布事件,这样我们就可以借助浏览器的 document 来实现一个不同组件之间数据的发布订阅,而不需要去借助第三方的 调度中心。
总结
本文我们稍微介绍了一下什么是自定义事件,并且简单的用了两个示例介绍了一下怎么去创建,以及参数的作用都是什么。两个自定义事件创建方式的区别主要在于 Event() 适合创建简单的自定义事件,而 CustomEvent() 支持参数传递的自定义事件,它支持 detail 参数,作为事件中需要被传递的数据,并在 EventListener 获取。所以我们可以根据我们实际的参数需求,去选择我们在业务开发中使用的创建方式,自定义事件对于数据传输来说,算是一个页面提供给我们的和便捷的方式。