事件总线是一种设计模式(虽然我们将在这里讨论JavaScript,但它在任何语言中都是一种设计模式),可用于简化不同组件之间的通信。它也可以被认为是发布/订阅或 pubsub。
其思想是,组件可以监听事件总线以了解何时执行其操作。例如,“选项卡面板”组件可能会监听指示其更改活动选项卡的事件。当然,这可能是由单击其中一个选项卡引起的,因此完全在该组件内处理。但是,使用事件总线,其他一些元素可以告诉选项卡进行更改。想象一下表单提交导致用户需要在特定选项卡中收到警报的错误,因此表单向事件总线发送消息,指示选项卡组件将活动选项卡更改为包含错误的选项卡。这就是它在事件总线上看起来的样子。
这种情况的伪代码如下所示……
// 选项卡组件 Tabs.changeTab = id => { // 更改活动选项卡的DOM操作。 }; MyEventBus.subscribe("change-tab", Tabs.changeTab(id)); // 其他组件... // 发生某些事情,然后: MyEventBus.publish("change-tab", 2);
您是否需要 JavaScript 库来实现此功能?(技巧问题:您永远不需要 JavaScript 库)。好吧,有很多选择:
- PubSubJS
- EventEmitter3
- Postal.js
- jQuery 甚至支持自定义事件,这与这种模式高度相关。
此外,请查看 Mitt,这是一个仅 200 字节 gzip 的库。这种简单的模式激发了人们以尽可能简洁的方式自己解决它的灵感。
让我们自己动手吧!我们根本不使用任何第三方库,而是利用 JavaScript 中已经内置的事件侦听系统,即我们都熟悉和喜爱的 addEventListener
。
首先,一些上下文
JavaScript 中的 addEventListener
API 是 EventTarget
类的成员函数。我们可以将点击事件绑定到按钮的原因是(HTMLButtonElement
)的原型接口间接继承自 EventTarget
。
与大多数其他 DOM 接口不同,可以使用 new
关键字直接创建 EventTarget
。它在所有现代浏览器中都受支持,但只是最近才支持。正如我们在上面的屏幕截图中看到的,Node
继承了 EventTarget
,因此所有 DOM 节点都有方法 addEventListener
。
诀窍
我建议使用一种极其轻量级的 Node 类型作为我们的事件侦听总线:HTML 注释(<!-- -->
)。
对于浏览器渲染引擎,HTML 注释只是代码中的注释,除了为开发人员提供描述性文本之外,没有任何功能。但是,由于注释仍然是用 HTML 编写的,因此它们最终作为真实的节点出现在 DOM 中,并具有自己的原型接口——Comment
——它继承自 Node
。
Comment
类可以直接从 new
创建,就像 EventTarget
一样:
const myEventBus = new Comment('my-event-bus');
我们也可以使用古老但广泛支持的 document.createComment
API。它需要一个数据参数,即注释的内容。它甚至可以是空字符串:
const myEventBus = document.createComment('my-event-bus');
现在我们可以使用 dispatchEvent
发出事件,它接受一个 Event
对象。要传递用户定义的事件数据,请使用 CustomEvent
,其中 detail
字段可用于包含任何数据。
myEventBus.dispatchEvent( new CustomEvent('event-name', { detail: 'event-data' }) );
Internet Explorer 9-11 支持 CustomEvent
,但没有任何版本支持 new CustomEvent
。使用 document.createEvent
模拟它很复杂,因此如果 IE 支持对您很重要,则有一种方法可以对其进行填充。
现在我们可以绑定事件侦听器:
myEventBus.addEventListener('event-name', ({ detail }) => { console.log(detail); // => event-data });
如果事件打算只触发一次,我们可以使用 { once: true }
进行一次性绑定。其他选项不适合这里。要删除事件侦听器,我们可以使用原生的 removeEventListener
。
调试
绑定到单个事件总线的事件数量可能非常大。如果您忘记删除它们,也可能存在内存泄漏。如果我们想知道有多少事件绑定到 myEventBus
呢?
myEventBus
是一个 DOM 节点,因此浏览器中的 DevTools 可以对其进行检查。在那里,我们可以在“元素”→“事件侦听器”选项卡中找到事件。请务必取消选中“祖先”以隐藏绑定到 document
和 window
上的事件。
示例
一个缺点是 EventTarget
的语法略显冗长。我们可以为它编写一个简单的包装器。下面是 TypeScript 中的演示:
class EventBus<detailtype any> { private eventTarget: EventTarget; constructor(description = '') { this.eventTarget = document.appendChild(document.createComment(description)); } on(type: string, listener: (event: CustomEvent<detailtype>) => void) { this.eventTarget.addEventListener(type, listener); } once(type: string, listener: (event: CustomEvent<detailtype>) => void) { this.eventTarget.addEventListener(type, listener, { once: true }); } off(type: string, listener: (event: CustomEvent<detailtype>) => void) { this.eventTarget.removeEventListener(type, listener); } emit(type: string, detail?: DetailType) { return this.eventTarget.dispatchEvent(new CustomEvent(type, { detail })); } } // 用法 const myEventBus = new EventBus<string>('my-event-bus'); myEventBus.on('event-name', ({ detail }) => { console.log(detail); }); myEventBus.once('event-name', ({ detail }) => { console.log(detail); }); myEventBus.emit('event-name', 'Hello'); // => Hello Hello myEventBus.emit('event-name', 'World'); // => World</string></detailtype></detailtype></detailtype></detailtype>
下面的演示提供了编译后的 JavaScript。
就是这样!我们刚刚创建了一个无依赖的事件侦听总线,一个组件可以通知另一个组件更改以触发操作。执行此类操作不需要完整的库,并且它开启的可能性是无限的。
以上是让我们在JavaScript中创建轻巧的本机活动巴士的详细内容。更多信息请关注PHP中文网其他相关文章!

这是我们在形式可访问性上进行的小型系列中的第三篇文章。如果您错过了第二篇文章,请查看“以:focus-visible的管理用户焦点”。在

本教程演示了使用智能表单框架创建外观专业的JavaScript表单(注意:不再可用)。 尽管框架本身不可用,但原理和技术仍然与其他形式的建筑商相关。

CSS盒子阴影和轮廓属性获得了主题。让我们查看一些在真实主题中起作用的示例,以及我们必须将这些样式应用于WordPress块和元素的选项。

Svelte Transition API提供了一种使组件输入或离开文档(包括自定义Svelte Transitions)时动画组件的方法。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

Dreamweaver CS6
视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3汉化版
中文版,非常好用