搜索
首页web前端css教程让我们在JavaScript中创建轻巧的本机活动巴士

Let’s Create a Lightweight Native Event Bus in JavaScript

事件总线是一种设计模式(虽然我们将在这里讨论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 可以对其进行检查。在那里,我们可以在“元素”→“事件侦听器”选项卡中找到事件。请务必取消选中“祖先”以隐藏绑定到 documentwindow 上的事件。

示例

一个缺点是 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中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
揭开屏幕读取器的神秘面纱:可访问的表格和最佳实践揭开屏幕读取器的神秘面纱:可访问的表格和最佳实践Mar 08, 2025 am 09:45 AM

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

使用智能表单框架创建JavaScript联系表格使用智能表单框架创建JavaScript联系表格Mar 07, 2025 am 11:33 AM

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

将框阴影添加到WordPress块和元素将框阴影添加到WordPress块和元素Mar 09, 2025 pm 12:53 PM

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

使用GraphQL缓存使用GraphQL缓存Mar 19, 2025 am 09:36 AM

如果您最近开始使用GraphQL或审查了其优点和缺点,那么您毫无疑问听到了诸如“ GraphQl不支持缓存”或

使您的第一个自定义苗条过渡使您的第一个自定义苗条过渡Mar 15, 2025 am 11:08 AM

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

展示,不要说展示,不要说Mar 16, 2025 am 11:49 AM

您花多少时间为网站设计内容演示文稿?当您撰写新的博客文章或创建新页面时,您是在考虑

优雅且酷的自定义CSS卷轴:展示柜优雅且酷的自定义CSS卷轴:展示柜Mar 10, 2025 am 11:37 AM

在本文中,我们将深入研究滚动条。我知道,这听起来并不魅力,但请相信我,一个精心设计的页面是齐头并进的

NPM命令是什么?NPM命令是什么?Mar 15, 2025 am 11:36 AM

NPM命令为您运行各种任务,无论是一次性或连续运行的过程,例如启动服务器或编译代码。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用