Przeglądaj źródła

feat: 增加eventBus

lanjianrong 3 lat temu
rodzic
commit
de39d27f02
3 zmienionych plików z 63 dodań i 0 usunięć
  1. 3 0
      src/enums/emit.ts
  2. 45 0
      src/utils/emit/event.ts
  3. 15 0
      src/utils/emit/index.ts

+ 3 - 0
src/enums/emit.ts

@@ -0,0 +1,3 @@
+export enum EmitterType {
+  BUSINESS_STEP_REFRESH = 'business_step_refresh'
+}

+ 45 - 0
src/utils/emit/event.ts

@@ -0,0 +1,45 @@
+import { cloneDeep } from 'lodash'
+import { useEffect, useRef } from 'react'
+type SubscriptionParams<T = any> = {
+  params: T
+  event: string | number
+}
+type Subscription<T> = ({ params, event }: SubscriptionParams<T>) => void
+class EventEmitter<T> {
+  private subscriptions = new Map<string | number, Subscription<T>>()
+  constructor() {
+    this.clear()
+  }
+  useSubscription = (event: string, listener?: Subscription<T>) => {
+    const callbackRef = useRef<Subscription<T>>()
+    useEffect(() => {
+      callbackRef.current = listener
+      function subscription(val: SubscriptionParams) {
+        if (callbackRef.current) {
+          callbackRef.current(val)
+        }
+      }
+      this.subscriptions.set(event, subscription)
+      return () => {
+        this.subscriptions.delete(event)
+      }
+    }, [])
+  }
+  emit = (event: string | number, ...args: T extends any[] ? any[] : any) => {
+    if (typeof event === 'string' || typeof event === 'number') {
+      const subscriptionValuesCallback = this.subscriptions.get(event)
+      subscriptionValuesCallback?.({
+        params: cloneDeep(args) as any,
+        event
+      })
+    } else throw new TypeError('event must be string or number !')
+  }
+  removeListener = (event: string) => {
+    this.subscriptions.delete(event)
+  }
+  clear = () => {
+    this.subscriptions.clear()
+  }
+}
+const eventEmitterOverall = new EventEmitter()
+export { EventEmitter, eventEmitterOverall }

+ 15 - 0
src/utils/emit/index.ts

@@ -0,0 +1,15 @@
+import { useEffect, useMemo, useRef } from 'react'
+import { EventEmitter, eventEmitterOverall } from './event'
+export default function useEventEmitter<T = void>(options?: { global?: boolean }) {
+  const ref = useRef<EventEmitter<T> | typeof eventEmitterOverall>()
+  const eventEmitterOptions = useMemo(() => options ?? { global: false }, [options])
+  if (!ref.current) {
+    ref.current = eventEmitterOptions.global
+      ? (ref.current = eventEmitterOverall)
+      : (ref.current = new EventEmitter())
+  }
+  useEffect(() => {
+    return () => ref.current?.clear()
+  }, [])
+  return ref.current
+}