首页 > 其他分享 >从0到1手写实现前端事件中心机制

从0到1手写实现前端事件中心机制

时间:2024-12-23 14:30:04浏览次数:9  
标签:订阅 中心 userLogin 前端 eventEmitter eventName 事件 手写 机制

1. 引言

在前端开发中,尤其是构建大型应用时,组件之间的通信变得非常复杂。为了实现组件之间的解耦,我们通常会采用事件驱动的方式。事件中心(Event Emitter)机制就是通过集中管理和分发事件来解耦生产者(事件的触发者)和消费者(事件的处理者)。这种机制尤其适合在复杂的前端应用中,减少组件之间的直接依赖。

本文将介绍如何从0到1实现一个简单的事件中心,并用 JavaScript 来构建,适合初学者理解。我们将一步步实现事件中心,并展示如何在实际的前端应用中使用它。

2. 事件中心的基本概念

2.1 事件中心的工作原理

事件中心的核心功能是“订阅”和“发布”事件。生产者通过事件中心发布事件,消费者则通过事件中心订阅感兴趣的事件。事件中心接收到事件时,会将其分发给相应的消费者。

  • 发布事件 :当某个组件发生了某种操作时,它会向事件中心发布一个事件。

  • 订阅事件 :其他组件可以订阅特定类型的事件,当事件发生时,事件中心会通知这些组件。

2.2 事件中心的优势

  • 解耦 :生产者不需要知道谁会处理事件,消费者也不需要知道事件是如何触发的。

  • 提高扩展性 :如果需要增加新的功能或模块,只需要订阅或发布事件,不需要修改现有代码。

  • 提高响应性 :事件可以是异步的,消费者可以在事件到达时进行异步处理,避免了同步执行可能带来的性能问题。

3. 手写实现事件中心

接下来,我们将用 JavaScript 从头开始实现一个简单的事件中心,支持事件的订阅和发布。

3.1 设计事件中心类

我们将首先设计一个 EventEmitter 类,这个类需要提供两个主要的功能:

  • on(eventName, callback):用于订阅事件。

  • emit(eventName, ...args):用于发布事件。

  • off(eventName, ...args):用于取消订阅事件。

我们可以使用 JavaScript 中的对象({})来存储事件类型和对应的回调函数队列。

3.2 代码实现

class EventEmitter {
    constructor () {
        this.events = {}
    }
    // 订阅事件
    on (eventName, callback) {
        if (!this.events[eventName]) {
            this.events[eventName] = []
        }
        this.events[eventName].push(callback)
        console.log(`Subscribed to event: ${eventName}`);
    }
    // 发布事件
    emit (eventName, ...args) {
        if (!this.events[eventName]) {
            return
        }
        this.events[eventName].map(callback => callback(...args))
        console.log(`Event emit: ${eventName}`);
    }
    // 取消订阅事件
    off (eventName, callback) {
        const eventCallbacks = this.events[eventName]
		if (!eventCallbacks) return
        this.events[eventName] = eventCallbacks.filter(cb => cb !== callback)
        console.log(`off event: ${eventName}`);
    } 
}

3.3 事件中心的使用

下面我们来看一下如何在实际的前端应用中使用这个事件中心。

// 创建一个事件中心实例
const eventEmitter = new EventEmitter();

// 定义事件的消费者回调
function onUserLogin(data) {
  console.log(`User logged in: ${data.username}`);
}

function onUserLogout(data) {
  console.log(`User logged out: ${data.username}`);
}

// 订阅事件
eventEmitter.on('userLogin', onUserLogin);
eventEmitter.on('userLogout', onUserLogout);

// 发布事件
eventEmitter.emit('userLogin', { username: 'kobe' });
eventEmitter.emit('userLogout', { username: 'jordan' });

// 取消订阅
// eventEmitter.off('userLogin', onUserLogin);
eventEmitter.emit('userLogin', { username: 'kobe' }); 


 
我们可以看到在注释掉off事件,可以看到kobe的logged in的信息

// 创建一个事件中心实例
const eventEmitter = new EventEmitter();

// 定义事件的消费者回调
function onUserLogin(data) {
  console.log(`User logged in: ${data.username}`);
}

function onUserLogout(data) {
  console.log(`User logged out: ${data.username}`);
}

// 订阅事件
eventEmitter.on('userLogin', onUserLogin);
eventEmitter.on('userLogout', onUserLogout);

// 发布事件
eventEmitter.emit('userLogin', { username: 'kobe' });
eventEmitter.emit('userLogout', { username: 'jordan' });

// 取消订阅
eventEmitter.off('userLogin', onUserLogin);
eventEmitter.emit('userLogin', { username: 'kobe' });  // 不会触发回调

 

但是当我们正常触发off事件时,就看不到kobe的logged in的信息
 

3.4 解释代码

  • on方法 :用于订阅某个事件。当某个组件对某个事件感兴趣时,它会调用 on方法,传入事件类型和回调函数。事件中心将这个回调函数保存在一个数组中,当事件发布时,会依次执行这些回调函数。

  • emit方法 :用于发布事件。发布者不需要知道谁会处理事件,它只需要向事件中心发布一个事件,并附带数据。事件中心会遍历所有订阅了该事件类型的回调函数并执行它们。

  • off方法 :如果某个组件不再关心某个事件,可以调用 off 方法,取消对该事件的订阅。

4. 事件中心的应用场景

4.1 用户登录/登出事件

在一个大型的前端应用中,用户登录和登出是非常常见的场景。当用户登录或登出时,可能需要执行一些操作(如更新UI、获取用户信息、重定向页面等)。通过事件中心,我们可以将这些操作解耦,避免紧耦合的逻辑。

例如,当用户登录时,我们可以触发 userLogin 事件,其他组件(如用户信息模块、UI模块等)可以订阅这个事件,并在事件触发时执行相应的操作。

4.2 表单提交

在一个表单提交的场景中,用户输入数据并提交表单时,可能会触发多个操作(如数据验证、请求发送、显示加载状态等)。通过事件中心,我们可以将这些操作分开处理,避免在同一个地方处理所有逻辑,简化代码。

4.3 组件间通信

在前端开发中,尤其是单页面应用(SPA)中,多个组件之间经常需要进行通信。通过事件中心机制,组件之间可以通过事件来交换数据,而不需要直接调用其他组件的方法或修改它们的状态。

5. 优化与扩展

5.1 异步处理

我们可以通过异步方式来处理事件,使得事件的消费更加高效。比如可以使用 setTimeoutPromise 来异步执行回调函数,避免阻塞主线程。

5.2 支持一次性订阅

我们可以添加一个一次性订阅功能,使得某些事件只会被触发一次后自动取消订阅。这在某些场景下会非常有用。

once (eventName, callback) {
  const onceCallback = (...args) => {
    callback(...args)
	// 这块注意是onceCallback,而不是callback
    this.off(eventName, onceCallback)
    // console.log(`once event: ${eventName}`);
  }
  this.on(eventName, onceCallback)
}

// 调用一下
eventEmitter.once('userLogin', onUserLogin); 
eventEmitter.emit('userLogin', { username: 'durant' });
eventEmitter.emit('userLogin', { username: 'durant' });


 
可以看到user logged in: durant只有一次调用

6. 总结

本文通过从0到1的方式实现了一个简单的事件中心,并讲解了如何在前端应用中使用它来解耦组件之间的通信。事件中心可以帮助我们处理异步事件、提高系统扩展性并简化代码结构,尤其适合用于大型前端应用中的组件间通信。通过本文的代码实现,相信你已经能掌握事件中心的基本原理和使用方法,并能在实际项目中加以应用。

标签:订阅,中心,userLogin,前端,eventEmitter,eventName,事件,手写,机制
From: https://blog.csdn.net/yinzhixiaxue/article/details/144610498

相关文章

  • Redis 持久化机制详解
    一、Redis持久化机制之基石:引言在当今数据驱动的时代,数据的安全性与可靠性犹如基石之于高楼,其重要性不言而喻。Redis,这款广受欢迎的内存数据库,以其卓越的性能在众多应用场景中大放异彩。然而,内存数据的易失性始终是一把悬于头顶的达摩克利斯之剑,一旦服务器遭遇意外,如宕机、断......
  • 前端 HTTP 请求由 Nginx 反向代理和 API 网关到后端服务的流程
    在大型互联网项目中,前端发送请求通过Nginx等反向代理和网关组件传递到后端服务的过程是一个复杂且精细的系统流程。从微服务架构的角度,这个过程可以分为以下几个主要步骤,并可能涉及其他中间组件,如监控和日志组件等。一、前端发送请求用户交互:用户在前端界面(如网页或移动......
  • 记录一次「OSS上传文件的前置处理机制」实例剖析
    作者:京东物流陈雨引言在云计算环境中,对象存储服务(OSS)是一种提供存储和访问任意类型数据(如网站内容、企业备份数据、游戏、IoT设备数据等)的服务,支持从任何地点、任何时间访问数据。在很多应用场景中,用户需要上传文件到OSS,这可能包括图片、视频、文档等多种格式的文件。为了提......
  • 运维系列&前端系列:echarts超出容器宽度问题的解决办法
    echarts超出容器宽度问题的解决办法echarts超出容器宽度问题的解决办法问题:解决方法:echarts超出容器宽度问题的解决办法问题:在使用vue+iview+echarts时,出现了echarts图标刷新页面会超出容器宽度的问题,效果如下:DOM结构:JS代码:解决方法:在网上查找了很多方......
  • 前端开发必备:这些 Shell 命令你都会用吗?
    在前端开发中,Shell命令是一项提升效率的必备技能。从项目初始化到代码构建、从版本控制到文件操作,熟练使用Shell命令可以显著优化开发流程。本篇文章将为您系统梳理前端开发中常用的Shell命令,帮助您在日常工作中快速上手,提高开发效率。不论您是前端新手还是资深开发者......
  • 前端-如何把手风琴和表格融合一起
    效果示意图:模板代码:<divstyle="width:80%;overflow-x:scroll;overflow-y:scroll"><divstyle="margin-top:5px;height:500px"><tableclass="header-table"><thead><......
  • 108. Web前端网页案例——【国粹京剧文化主题精品网页( 5页)】 大学生期末大作业 html5+
    目录一、网页概述二、网页文件三、网页效果四、代码展示1.html2.CSS3.JS五、总结1.简洁实用2.使用方便3.整体性好4.形象突出5.交互式强六、更多推荐♬♬♬欢迎光临我的CSDN!这里是Web前端网页案例大集汇,有各行各业的前端网页案例,每天会持续更新!如果你对Web前端......
  • AI文字界面描述生成原型与前端代码
    场景   之前文章也有介绍AI助力生成原型与UI前端代码第一回代码自动生成:AI大模型可以根据用户提供的文字界面描述,自动生成前端代码,如HTML、CSS和JavaScript。这种自动化过程显著减少了手动编写代码的时间和工作量,提高了开发效率。例如,开发者只需提供界面的草图或描述性语言,AI......
  • 110. Web前端网页案例——【2022冬奥会精品精品网页( 7页)】 大学生期末大作业 html+css
    目录一、网页概述二、网页文件三、网页效果四、代码展示1.html2.CSS五、总结1.简洁实用2.使用方便3.整体性好4.形象突出5.交互式强六、更多推荐♬♬♬欢迎光临我的CSDN!这里是Web前端网页案例大集汇,有各行各业的前端网页案例,每天会持续更新!如果你对Web前端网页......
  • 171. 大学生HTML5期末大作业 ―【 高端大气的美食网页(6页)】 Web前端网页制作 html5+cs
    目录一、网页概述二、网页文件三、网页效果四、代码展示1.html2.CSS五、总结1.简洁实用2.使用方便3.整体性好4.形象突出5.交互式强欢迎来到我的CSDN主页!Web前端网页制作、大学生期末大作业、课程设计、毕业设计、网页模版源码、学习资料等,更多优质博客文章、网......