Skip to content

Commit

Permalink
improvement(useevent): complete useEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
innocces committed Jul 4, 2021
1 parent d9a72d8 commit 97c44a0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 36 deletions.
4 changes: 4 additions & 0 deletions packages/app/src/constant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export const ChildrenList: { [_: string]: APIChildrenItem[] } = {
id: 'useAPICheck',
name: 'useAPICheck 判断是否可用',
},
{
id: 'useEvent',
name: 'useEvent 事件中心',
},
{
id: 'useBase64ToArrayBuffer',
name: 'useBase64ToArrayBuffer 转换base64',
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/pages/useEvent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export default () => {

const handleSetListenerOnce = useCallback(() => {
setListenerOnce(eventName + '-once', handler);
Taro.atMessage({
message: '设置监听成功(once)',
});
}, [setListenerOnce, handler]);

const handleEmitEvent = useCallback(
Expand Down
87 changes: 51 additions & 36 deletions packages/hooks/src/useEvent/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { useCallback, useContext, useReducer } from 'react';
import { context, wrapperEvent } from '../context';
import { typeOf } from '../utils/tool';

export type eventHandler = (...args: any[]) => void;

export interface IEventQueue {
[_: string]: ((...args: any[]) => void)[];
[_: string]: eventHandler[];
}

export interface IActionAddPayload {
eventName: string;
handlers: ((...args: any[]) => void)[];
handler?: (...args: any[]) => void;
handlers: eventHandler[];
handler?: eventHandler;
params?: any[];
}
export interface IActionTriggerPayload {
eventName: string;
params: any[];
}

export interface IActionOffPayload {
eventName: string;
handler?: eventHandler;
}

export interface IState {
eventQueue: IEventQueue;
eventNameQueue: string[];
Expand All @@ -31,13 +39,17 @@ export enum IActionType {

export interface IAction {
type: IActionType;
payload: string | string[] | IActionAddPayload | IActionTriggerPayload | null;
payload:
| string
| string[]
| IActionAddPayload
| IActionTriggerPayload
| IActionOffPayload
| null;
}

export const safeNamespace = ['__taro', 'at'];

declare function sideEffectHandler<U extends any[]>(...args: U): void;

const initState: IState = {
eventQueue: {},
eventNameQueue: [],
Expand All @@ -47,7 +59,7 @@ function useEvent(namespace: string) {
const { eventBus } = useContext(context);

const setListener = useCallback(
(eventName: string, ...handlers: ((...args: any[]) => void)[]) => {
(eventName: string, ...handlers: eventHandler[]) => {
if (!eventName || safeNamespace.some((v) => eventName.startsWith(v))) {
console.warn('eventName not valid. listen failed');
} else if (!handlers.length) {
Expand All @@ -66,7 +78,7 @@ function useEvent(namespace: string) {
);

const setListenerOnce = useCallback(
(eventName: string, handler: (...args: any[]) => void) => {
(eventName: string, handler: eventHandler) => {
if (!eventName || !handler) {
console.warn('you must provide eventName and handler');
return;
Expand Down Expand Up @@ -101,16 +113,25 @@ function useEvent(namespace: string) {
}, []);

const safeRemoveEvents = useCallback(
(eventNameQueue: string[], eventQueue): IEventQueue => {
(
eventNameQueue: string[],
eventQueue,
...handlers: eventHandler[]
): IEventQueue => {
const removeEventName = eventNameQueue.filter(
(v) => !safeNamespace.some((n) => v.startsWith(n)),
);

removeEventName.forEach((v) => eventBus.off(v));
removeEventName.forEach((v) => eventBus.off(v, ...(handlers || [])));
const offQueue: IEventQueue = {};
if (eventNameQueue.length === 1 && removeEventName.length) {
Object.keys(eventQueue).forEach((key) => {
if (!eventNameQueue.includes(key)) {
// check if has handlers
if (handlers && eventNameQueue.includes(key)) {
offQueue[key] = eventQueue[key].filter(
(v: eventHandler) => !handlers.includes(v),
);
} else if (!eventNameQueue.includes(key)) {
offQueue[key] = eventQueue[key];
}
});
Expand All @@ -130,6 +151,8 @@ function useEvent(namespace: string) {
eventQueue: {},
eventNameQueue: [],
};
} else if (!typeOf(payload, ['String', 'Array'])) {
return state;
} else {
return {
eventNameQueue: state.eventNameQueue.filter((v) => v !== payload),
Expand All @@ -142,6 +165,19 @@ function useEvent(namespace: string) {
case IActionType.OFF:
if (!payload) {
return state;
} else {
return {
eventNameQueue: state.eventNameQueue.filter(
(v) => v !== (payload as IActionOffPayload).eventName,
),
eventQueue: safeRemoveEvents(
[(payload as IActionOffPayload).eventName],
state.eventQueue,
(payload as IActionOffPayload).handler as (
...args: any[]
) => void,
),
};
}
case IActionType.ADD:
if (
Expand Down Expand Up @@ -207,7 +243,7 @@ function useEvent(namespace: string) {
case IActionType.ONCE:
setListenerOnce(
(payload as IActionAddPayload).eventName,
(payload as IActionAddPayload).handler as (...args: any[]) => void,
(payload as IActionAddPayload).handler as eventHandler,
);
return state;
default:
Expand All @@ -219,33 +255,12 @@ function useEvent(namespace: string) {
const [state, dispatch] = useReducer(reducer, initState);

const removeListener = useCallback(
(eventName?: string, handler?: (...args: any[]) => void) => {
// clearListener(eventName, handler);
const { eventNameQueue, eventQueue } = state;
if (!eventNameQueue) {
console.warn('there is no event to clear');
return;
}
(eventName?: string, handler?: eventHandler) => {
const realEventName = eventName && wrapperEvent(namespace, eventName);
console.log(realEventName, eventNameQueue, state);
if (!realEventName || !eventNameQueue.includes(realEventName)) {
console.warn(
"you don't provide eventName, it will remove all listener. Thoese listeners will be remove: ",
);
console.table(eventQueue);
}

if (realEventName && eventNameQueue.includes(realEventName)) {
console.log('Thoese listeners will be remove: ');
console.table({
[eventName as string]: eventQueue[realEventName],
});
}
dispatch({
type: realEventName ? IActionType.OFF : IActionType.CLEAR,
payload: realEventName
? { eventName: realEventName, handlers: handler ? [handler] : [] }
: null,
payload: realEventName ? { eventName: realEventName, handler } : null,
});
},
[state],
Expand Down

0 comments on commit 97c44a0

Please sign in to comment.