ahooks源码阅读之useEventEmitter

useEventEmitter

在多个组件之间进行事件通知有时会让人非常头疼,借助 EventEmitter ,可以让这一过程变得更加简单。

参考:useEventEmitter

源码

import { useRef, useEffect } from "react";

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

export class EventEmitter<T> {
  // 采用Set存储订阅回调
  private subscriptions = new Set<Subscription<T>>();

  // 遍历回调函数
  emit = (val: T) => {
    for (const subscription of this.subscriptions) {
      subscription(val);
    }
  };

  useSubscription = (callback: Subscription<T>) => {
    const callbackRef = useRef<Subscription<T>>();
    callbackRef.current = callback;
    useEffect(() => {
      // 订阅
      function subscription(val: T) {
        if (callbackRef.current) {
          callbackRef.current(val);
        }
      }
      this.subscriptions.add(subscription);
      return () => {
        this.subscriptions.delete(subscription);
      };
    }, []);
  };
}

export default function useEventEmitter<T = void>() {
  const ref = useRef<EventEmitter<T>>();
  if (!ref.current) {
    ref.current = new EventEmitter();
  }
  return ref.current;
}
复制代码

使用

import React, { useRef, FC } from "react";
import { useEventEmitter } from "ahooks";
import { EventEmitter } from "ahooks/lib/useEventEmitter";

const MessageBox: FC<{
  focus$: EventEmitter<void>;
}> = function (props) {
  return (
    <div style={{ paddingBottom: 24 }}>
      <p>You received a message</p>
      <button
        type="button"
        onClick={() => {
          props.focus$.emit();
        }}>
        Reply
      </button>
    </div>
  );
};

const InputBox: FC<{
  focus$: EventEmitter<void>;
}> = function (props) {
  const inputRef = useRef<any>();
  // =。=这里使用的是EventEmitter的实例返回的useSubscription,与一般hooks用法不同。这样就能访问到实例存储的回调集合
  props.focus$.useSubscription(() => {
    inputRef.current.focus();
  });
  return (
    <input
      ref={inputRef}
      placeholder="Enter reply"
      style={{ width: "100%", padding: "4px" }}
    />
  );
};

export default function () {
  const focus$ = useEventEmitter();
  return (
    <>
      <MessageBox focus$={focus$} />
      <InputBox focus$={focus$} />
    </>
  );
}
复制代码

对比 eventEmitter3.js 可以看出,还有非常多方法值得扩展

eventEmitter3.jpg

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享