当前位置: 首页 > news >正文

前端小技巧: TS实现EventBus自定义事件

关于EventBus事件总线

  • 事件总线,实现 on, once, emit, off
    • on, once 是注册函数,存储起来
    • emit时找到对应的函数,执行
    • off找到对应的函数,从对象中删除
  • 注意
    • 区分on和once
    • on绑定的事件可连续执行,除非off
    • once绑定的函数 emit 一次即删除,也可未执行而被 off
    • 数据结构上标识出 on 和 once

实现方案1

代码实现:使用参数区分 on和once

class EventBus {/*{key1: [{fn: fn1, isOnce: false},{fn: fn2, isOnce: false},{fn: fn3, isOnce: true},],key2: []}*/private events: {[key: string]: Array<{fn: Function; isOnce: boolean}>}constructor() {this.events = {};}on(type: string, fn: Function, isOnce: boolean = false) {const events = this.events;if (events[type] == null) {events[type] = []; // 初始化 key 的 fn 数组}events[type].push({fn, isOnce});},// 这里是初步版本once_origin(type: string, fn: Function) {const events = this.events;if (events[type] == null) {events[type] = []; // 初始化 key 的 fn 数组}events[type].push({fn, isOnce: true});},once(type: string, fn: Function, isOnce: boolean = false) {this.on(type, fn, true);},off(type: string, fn?:Function) {if (!fn) {// 解绑所有 type 的函数this.events[type] = [];} else {// 解绑单个 fnconst fnList = this.events[type];if (fnList.length) {this.events[type] = fnList.filter(item.fn !== fn);}}},emit(type: string, ...args: any[]) {const fnList = this.events[type];if (fnList == null) return;// 注意this.events[type] = fnList.filter(item => {const { fn, isOnce } = item;fn(...args);// 处理once, 它执行一次就要被过滤掉if (!isOnce) return true;return false;})}
}const e = new EventBus();
function fn1(a: any, b: any) {console.log('fn1', a, b)};
function fn2(a: any, b: any) {console.log('fn2', a, b)};
function fn3(a: any, b: any) {console.log('fn3', a, b)};e.on('key1', fn1);
e.on('key1', fn2);
e.once('key1', fn3);e.emit('key1', 10, 20); // 触发 fn1, fn2, fn3
e.off('key1', fn1);
e.emit('key1', 100, 200); // 触发 fn2

实现方案2

代码实现: 拆分保存 on和once

class EventBus {private events: { [key: string]: Array<Function>} // {key1: [fn1, fn2]}private onceEvents: {[key: string]: Array<Function>} // 结构同上constructor() {this.events = {}; // 存储 onthis.onceEvents = {}; // 存储 once}// on 触发on(type: string, fn: Function) {const events = this.events;if (events[type] === null) events[type] = [];events[type].push(fn);},once(type: string, fn: Function) {const onceEvents = this.onceEvents;if (onceEvents[type] === null) onceEvents[type] = [];onceEvents[type].push(fn);},// 解绑事件off(type: string, fn: Function) {if (!fn) {// 解绑所有事件this.events[type] = [];this.onceEvents[type] = [];} else {// 解绑单个const fnList = this.events[type];const onceFnList = this.onceEvents[type];if (fnList.length) {this.events[type] = fnList.filter(curFn => curFN!== fn);}if (onceFnList.length) {this.onceEvents[type] = onceFnList.filter(curFn => curFN!== fn);}}},emit(type: string, ...args: any[]) {const fnList = this.events[type];const onceFnList = this.onceEvents[type];if (fnList.length) {fnList.forEach(f => f(...args));}if (onceFnList.length) {onceFnList.forEach(f => f(...args));// once 执行一次就删除,这里更简单,代码更简洁this.onceEvents[type] = [];}}
}// 测试用例同上,此处省略

总结

  • 区分 on, once
  • 合理的数据结构,比算法优化更有效

相关文章:

前端小技巧: TS实现EventBus自定义事件

关于EventBus事件总线 事件总线&#xff0c;实现 on, once, emit, off on, once 是注册函数&#xff0c;存储起来emit时找到对应的函数&#xff0c;执行off找到对应的函数&#xff0c;从对象中删除 注意 区分on和onceon绑定的事件可连续执行&#xff0c;除非offonce绑定的函数…...

Django之三板斧的使用,全局配置文件介绍,request对象方法,pycharm链接数据库,Django链接数据库,ORM的增删改查

【1】三板斧(3个方法)的使用 Httpresponse() 括号内写什么字符串&#xff0c;返回的就是什么字符串返回的是字符串 render(request&#xff0c; 静态文件 ) request是固定的静态文件是写在templates文件夹里面的&#xff0c;如&#xff0c;HTML文件 redirect( 重定向的地址 ) 重…...

医学影像系统源码(MRI、CT三维重建)

一、MRI概述 核磁共振成像&#xff08;英语&#xff1a;Nuclear Magnetic Resonance Imaging&#xff0c;简称NMRI&#xff09;&#xff0c;又称自旋成像&#xff08;英语&#xff1a;spin imaging&#xff09;&#xff0c;也称磁共振成像&#xff08;Magnetic Resonance Imag…...

【uniapp】仿微信通讯录列表实现

效果图 代码实现 <view class"main-container"><!-- 成员列表 --><scroll-viewclass"member-list":style"computedHeight":scroll-y"true":enable-back-to-top"true":scroll-with-animation"true"…...

[MT8766][Android12] 增加应用安装白名单或者黑名单

文章目录 开发平台基本信息问题描述解决方法 开发平台基本信息 芯片: MT8766 版本: Android 12 kernel: msm-4.19 问题描述 在项目开发的时候&#xff0c;经常有一些客户&#xff0c;要求系统安装应用的时候需要进行验签&#xff1b;也就是系统默认不允许任何应用安装&#…...

游戏公司数据分析师必备知识(持续补充中...)

1.如何撰写专题报告&#xff1f; ①原则 只有一个主题&#xff1a;即使不讲ppt&#xff0c;业务方也能看得懂行文通俗简单易懂&#xff1a;学习产品经理平常是如何写报告的明确的数据结论和落地项先行&#xff1a;跟业务方多沟通数据结论&#xff0c;让他们给出落地项 ②结构…...

intellj 开发软件插件

IDEA&#xff1a; .ignore Alibaba Java Coding Guidelines(XenoAmess TPM) Chinese (Simplified) Language Pack / 中文语言包 CodeGlance Pro Gitee Grep Console Json Formatter Maven Helper Nyan Progress Bar One Dark theme Python Rainbow Brackets Resource Bundle Ed…...

leetCode 493 翻转对

给定一个数组 nums &#xff0c;如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。 未完待续~...

“辛巴猫舍”内网渗透、提权、撞库学习笔记

前言&#xff1a; 在拿到靶机时&#xff0c;我们最先需要做的是信息收集&#xff0c;包括不限于&#xff1a;C段扫描&#xff0c;端口探测&#xff0c;指纹识别&#xff0c;版本探测等。其次就是 漏洞挖掘、漏洞利用、提权、维持权限、日志清理、留下后门。 以上就是渗透的基本…...

粤嵌实训医疗项目--day06(Vue + SpringBoot)

往期回顾 粤嵌实训医疗项目(小组开发)--day05-CSDN博客粤嵌实训医疗项目--day04&#xff08;Vue SpringBoot&#xff09;-CSDN博客粤嵌实训医疗项目--day03&#xff08;Vue SpringBoot&#xff09;-CSDN博客粤嵌实训医疗项目day02&#xff08;Vue SpringBoot&#xff09;-CS…...

SPSS二元Logistic回归

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…...

前端-第一部分-HTML

一.初识HTML 1.1 HTML 简介 HTML 全称为 HyperText Mark-up Language&#xff0c;翻译为超文本标签语言&#xff0c;标签也称作标记或者元素。HTML 是目前网络上应用最为广泛的技术之一&#xff0c;也是构成网页文档的主要基石之一。HTML文本是由 HTML 标签组成的描述性文本&a…...

六度空间(C++)

目录 题目&#xff1a; 输入、输出格式&#xff1a; 代码&#xff1a; 运行结果&#xff1a; 题目&#xff1a; 输入、输出格式&#xff1a; 代码&#xff1a; #include<iostream> #include<algorithm> using namespace std; int g[10005][10005]; float n…...

记录undefined reference to `SSLv3_client_method‘错误笔记

libcurl.a(libcurl_la-openssl.o): in function ossl_connect_step1: openssl.c:(.text0x3ca8): undefined reference to SSLv3_client_method 我个人环境原因&#xff1a;编译选项指定了某个openssl目录&#xff0c;此目录下有libcrypto.a libssl.a 解决方法&#xff1a;…...

JS算法练习 11.11

leetcode 2619 数组原型对象的最后一个元素 请你编写一段代码实现一个数组方法&#xff0c;使任何数组都可以调用 array.last() 方法&#xff0c;这个方法将返回数组最后一个元素。如果数组中没有元素&#xff0c;则返回 -1 。 你可以假设数组是 JSON.parse 的输出结果。 示例…...

50代码审计-PHP无框架项目SQL注入挖掘

代码设计分为有框架和无框架 挖掘技巧&#xff1a;随机挖掘&#xff0c;定点挖掘&#xff0c;批量挖掘&#xff08;用工具帮助扫描探针&#xff0c;推荐工具&#xff1a;fortify&#xff0c;seay系统&#xff09;。 1.教学计划&#xff1a; ---审计项目漏洞 Demo->审计思…...

什么是微服务?与分布式又有什么区别?

什么是微服务&#xff0c;我们先从传统的单体结构进行了解&#xff0c;对两者进行对比。 单体结构 单体结构是一种传统的软件架构模式&#xff0c;它将应用程序划分为一组相互依赖的模块和组件。这些模块和组件通常都是构建在同一个平台上的&#xff0c;并且紧密耦合在一起。…...

案例 | 3D可视化工具HOOPS助力SolidWorks edrawings成功引入AR/VR技术

HOOPS中文网慧都科技是HOOPS全套产品中国地区指定授权经销商&#xff0c;提供3D软件开发工具HOOPS售卖、试用、中文试用指导服务、中文技术支持。http://techsoft3d.evget.com/达索系统SolidWorks面临的挑战 达索系统SolidWorks公司开发和销售三维CAD设计软件、分析软件和产品…...

初识Linux:目录路径

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 一、基本指令&#xff1a; 二、文件 文件内容文件属性 三、ls 指令拓展 1、 ls -l &#xff1a; 2、ls -la&#xff1a; 3、ls [目录名] &#xff1a; 4、ls -ld [目录名]&#xff1a; 四、Linux中的文件和…...

抖音小程序开发:探索技术创新的代码之旅

随着抖音小程序的兴起&#xff0c;企业纷纷将目光投向这个充满活力的平台。抖音小程序开发不仅为品牌提供了更广泛的曝光机会&#xff0c;更是技术创新的舞台。本文将带领读者深入探索抖音小程序开发的技术要点&#xff0c;探讨如何通过代码实现个性化、高效的小程序。 1. 小…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...