[ahooks] useEventEmitter源码阅读

在React项目中如果涉及到在多个组件中进行通信,可以使用这个hooks

使用方式

tsx 复制代码
// 初始化
const event = useEventEmitter();

// 发送一个事件
event.emit("hello");

// 订阅通知, 当调用emit函数时,所有订阅的位置都会收到通知
event.useSubscription(val => {
  console.log(val);
});

源码

源码的核心是一个发布订阅类EventEmitter,里面包括一个订阅的Set集合subscriptions,发送方法emit和订阅方法useSubscription,底部是一个封装好的初始化hooksuseEventEmitter:

tsx 复制代码
import { useRef, useEffect } from 'react';

type Subscription<T> = (val: T) => void;

export class EventEmitter<T> {
  private subscriptions = new Set<Subscription<T>>();
  
  emit = (val: T) => {
    for (const subscription of this.subscriptions) {
      subscription(val);
    }
  };

  useSubscription = (callback: Subscription<T>) => {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const callbackRef = useRef<Subscription<T>>(undefined);
    callbackRef.current = callback;
    // eslint-disable-next-line react-hooks/rules-of-hooks
    useEffect(() => {
      function subscription(val: T) {
        if (callbackRef.current) {
          callbackRef.current(val);
        }
      }
      this.subscriptions.add(subscription);
      return () => {
        this.subscriptions.delete(subscription);
      };
    }, []);
  };
}

function useEventEmitter<T = void>() {
  const ref = useRef<EventEmitter<T>>(undefined);
  if (!ref.current) {
    ref.current = new EventEmitter();
  }
  return ref.current;
}

export default useEventEmitter;

subscriptions

用于保存所有已被订阅的事件,使用Set集合可以保证所有方法在全局只被注册一次

emit

用于发送事件通知,当调用emit方法时,会遍历subscriptions集合,通知所有已订阅的事件

useSubscription

用于订阅事件的hooks,内部使用useRef接收一个传入的事件,目的是为了保证每次在useEffect中调用的callback是最新的,避免闭包陷进

内部使用useEffect的原因是为了保证每个订阅的事件只在组件首次挂载时订阅一次,在组件卸载时取消订阅,这样获得更好的性能

useEventEmitter

最后是底部的useEventEmitter,它的作用是初始化EventEmitter类且返回一个该类的实例,使用useRef的目的是为了保证在调用该hooks的组件中,EventEmitter类只实例化一次

相关推荐
风度前端14 分钟前
npm 2026安全新规下的免登录发包策略
前端
冴羽29 分钟前
2026 年前端必须掌握的 4 个 CSS 新特性!
前端·javascript·css
rgeshfgreh42 分钟前
Python流程控制:从条件到循环实战
前端·数据库·python
狗头大军之江苏分军1 小时前
告别旧生态:Ant Design 6 不再支持 IE 与现代前端趋势解读
前端·javascript·后端
C_心欲无痕1 小时前
nginx - 开启 gzip 压缩
运维·前端·nginx
闲云一鹤1 小时前
2026 最新 ComfyUI 教程 - 本地部署 AI 生图模型 - Z-Image-Turbo
前端·人工智能·ai编程
开开心心_Every1 小时前
安卓后台录像APP:息屏录存片段,行车用
java·服务器·前端·学习·eclipse·edge·powerpoint
狗头大军之江苏分军1 小时前
Ant Design 6.0 正式发布:从 V5 到 V6 有哪些变化?
前端
Highcharts.js1 小时前
Highcharts Grid 表格/网格安装 |官方安装文档说明
开发语言·javascript·表格组件·highcharts·官方文档·安装说明·网格组件
优弧1 小时前
Claude 终于对普通人下手了!Cowork 发布,你的最强 AI 打工搭子来了!
前端·后端