前端小技巧: 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事件总线 事件总线,实现 on, once, emit, off on, once 是注册函数,存储起来emit时找到对应的函数,执行off找到对应的函数,从对象中删除 注意 区分on和onceon绑定的事件可连续执行,除非offonce绑定的函数…...
Django之三板斧的使用,全局配置文件介绍,request对象方法,pycharm链接数据库,Django链接数据库,ORM的增删改查
【1】三板斧(3个方法)的使用 Httpresponse() 括号内写什么字符串,返回的就是什么字符串返回的是字符串 render(request, 静态文件 ) request是固定的静态文件是写在templates文件夹里面的,如,HTML文件 redirect( 重定向的地址 ) 重…...
医学影像系统源码(MRI、CT三维重建)
一、MRI概述 核磁共振成像(英语:Nuclear Magnetic Resonance Imaging,简称NMRI),又称自旋成像(英语:spin imaging),也称磁共振成像(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 问题描述 在项目开发的时候,经常有一些客户,要求系统安装应用的时候需要进行验签;也就是系统默认不允许任何应用安装&#…...
游戏公司数据分析师必备知识(持续补充中...)
1.如何撰写专题报告? ①原则 只有一个主题:即使不讲ppt,业务方也能看得懂行文通俗简单易懂:学习产品经理平常是如何写报告的明确的数据结论和落地项先行:跟业务方多沟通数据结论,让他们给出落地项 ②结构…...
intellj 开发软件插件
IDEA: .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 ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。 未完待续~...
“辛巴猫舍”内网渗透、提权、撞库学习笔记
前言: 在拿到靶机时,我们最先需要做的是信息收集,包括不限于:C段扫描,端口探测,指纹识别,版本探测等。其次就是 漏洞挖掘、漏洞利用、提权、维持权限、日志清理、留下后门。 以上就是渗透的基本…...
粤嵌实训医疗项目--day06(Vue + SpringBoot)
往期回顾 粤嵌实训医疗项目(小组开发)--day05-CSDN博客粤嵌实训医疗项目--day04(Vue SpringBoot)-CSDN博客粤嵌实训医疗项目--day03(Vue SpringBoot)-CSDN博客粤嵌实训医疗项目day02(Vue SpringBoot)-CS…...
SPSS二元Logistic回归
前言: 本专栏参考教材为《SPSS22.0从入门到精通》,由于软件版本原因,部分内容有所改变,为适应软件版本的变化,特此创作此专栏便于大家学习。本专栏使用软件为:SPSS25.0 本专栏所有的数据文件请点击此链接下…...
前端-第一部分-HTML
一.初识HTML 1.1 HTML 简介 HTML 全称为 HyperText Mark-up Language,翻译为超文本标签语言,标签也称作标记或者元素。HTML 是目前网络上应用最为广泛的技术之一,也是构成网页文档的主要基石之一。HTML文本是由 HTML 标签组成的描述性文本&a…...
六度空间(C++)
目录 题目: 输入、输出格式: 代码: 运行结果: 题目: 输入、输出格式: 代码: #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 我个人环境原因:编译选项指定了某个openssl目录,此目录下有libcrypto.a libssl.a 解决方法:…...
JS算法练习 11.11
leetcode 2619 数组原型对象的最后一个元素 请你编写一段代码实现一个数组方法,使任何数组都可以调用 array.last() 方法,这个方法将返回数组最后一个元素。如果数组中没有元素,则返回 -1 。 你可以假设数组是 JSON.parse 的输出结果。 示例…...
50代码审计-PHP无框架项目SQL注入挖掘
代码设计分为有框架和无框架 挖掘技巧:随机挖掘,定点挖掘,批量挖掘(用工具帮助扫描探针,推荐工具:fortify,seay系统)。 1.教学计划: ---审计项目漏洞 Demo->审计思…...
什么是微服务?与分布式又有什么区别?
什么是微服务,我们先从传统的单体结构进行了解,对两者进行对比。 单体结构 单体结构是一种传统的软件架构模式,它将应用程序划分为一组相互依赖的模块和组件。这些模块和组件通常都是构建在同一个平台上的,并且紧密耦合在一起。…...
案例 | 3D可视化工具HOOPS助力SolidWorks edrawings成功引入AR/VR技术
HOOPS中文网慧都科技是HOOPS全套产品中国地区指定授权经销商,提供3D软件开发工具HOOPS售卖、试用、中文试用指导服务、中文技术支持。http://techsoft3d.evget.com/达索系统SolidWorks面临的挑战 达索系统SolidWorks公司开发和销售三维CAD设计软件、分析软件和产品…...
初识Linux:目录路径
目录 提示:以下指令均在Xshell 7 中进行 一、基本指令: 二、文件 文件内容文件属性 三、ls 指令拓展 1、 ls -l : 2、ls -la: 3、ls [目录名] : 4、ls -ld [目录名]: 四、Linux中的文件和…...
抖音小程序开发:探索技术创新的代码之旅
随着抖音小程序的兴起,企业纷纷将目光投向这个充满活力的平台。抖音小程序开发不仅为品牌提供了更广泛的曝光机会,更是技术创新的舞台。本文将带领读者深入探索抖音小程序开发的技术要点,探讨如何通过代码实现个性化、高效的小程序。 1. 小…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
