Skip to content

Commit 97c44a0

Browse files
committed
improvement(useevent): complete useEvent
1 parent d9a72d8 commit 97c44a0

File tree

3 files changed

+58
-36
lines changed

3 files changed

+58
-36
lines changed

packages/app/src/constant/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ export const ChildrenList: { [_: string]: APIChildrenItem[] } = {
3838
id: 'useAPICheck',
3939
name: 'useAPICheck 判断是否可用',
4040
},
41+
{
42+
id: 'useEvent',
43+
name: 'useEvent 事件中心',
44+
},
4145
{
4246
id: 'useBase64ToArrayBuffer',
4347
name: 'useBase64ToArrayBuffer 转换base64',

packages/app/src/pages/useEvent/index.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export default () => {
2929

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

3437
const handleEmitEvent = useCallback(

packages/hooks/src/useEvent/index.ts

+51-36
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
import { useCallback, useContext, useReducer } from 'react';
22
import { context, wrapperEvent } from '../context';
3+
import { typeOf } from '../utils/tool';
4+
5+
export type eventHandler = (...args: any[]) => void;
36

47
export interface IEventQueue {
5-
[_: string]: ((...args: any[]) => void)[];
8+
[_: string]: eventHandler[];
69
}
7-
810
export interface IActionAddPayload {
911
eventName: string;
10-
handlers: ((...args: any[]) => void)[];
11-
handler?: (...args: any[]) => void;
12+
handlers: eventHandler[];
13+
handler?: eventHandler;
1214
params?: any[];
1315
}
1416
export interface IActionTriggerPayload {
1517
eventName: string;
1618
params: any[];
1719
}
20+
21+
export interface IActionOffPayload {
22+
eventName: string;
23+
handler?: eventHandler;
24+
}
25+
1826
export interface IState {
1927
eventQueue: IEventQueue;
2028
eventNameQueue: string[];
@@ -31,13 +39,17 @@ export enum IActionType {
3139

3240
export interface IAction {
3341
type: IActionType;
34-
payload: string | string[] | IActionAddPayload | IActionTriggerPayload | null;
42+
payload:
43+
| string
44+
| string[]
45+
| IActionAddPayload
46+
| IActionTriggerPayload
47+
| IActionOffPayload
48+
| null;
3549
}
3650

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

39-
declare function sideEffectHandler<U extends any[]>(...args: U): void;
40-
4153
const initState: IState = {
4254
eventQueue: {},
4355
eventNameQueue: [],
@@ -47,7 +59,7 @@ function useEvent(namespace: string) {
4759
const { eventBus } = useContext(context);
4860

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

6880
const setListenerOnce = useCallback(
69-
(eventName: string, handler: (...args: any[]) => void) => {
81+
(eventName: string, handler: eventHandler) => {
7082
if (!eventName || !handler) {
7183
console.warn('you must provide eventName and handler');
7284
return;
@@ -101,16 +113,25 @@ function useEvent(namespace: string) {
101113
}, []);
102114

103115
const safeRemoveEvents = useCallback(
104-
(eventNameQueue: string[], eventQueue): IEventQueue => {
116+
(
117+
eventNameQueue: string[],
118+
eventQueue,
119+
...handlers: eventHandler[]
120+
): IEventQueue => {
105121
const removeEventName = eventNameQueue.filter(
106122
(v) => !safeNamespace.some((n) => v.startsWith(n)),
107123
);
108124

109-
removeEventName.forEach((v) => eventBus.off(v));
125+
removeEventName.forEach((v) => eventBus.off(v, ...(handlers || [])));
110126
const offQueue: IEventQueue = {};
111127
if (eventNameQueue.length === 1 && removeEventName.length) {
112128
Object.keys(eventQueue).forEach((key) => {
113-
if (!eventNameQueue.includes(key)) {
129+
// check if has handlers
130+
if (handlers && eventNameQueue.includes(key)) {
131+
offQueue[key] = eventQueue[key].filter(
132+
(v: eventHandler) => !handlers.includes(v),
133+
);
134+
} else if (!eventNameQueue.includes(key)) {
114135
offQueue[key] = eventQueue[key];
115136
}
116137
});
@@ -130,6 +151,8 @@ function useEvent(namespace: string) {
130151
eventQueue: {},
131152
eventNameQueue: [],
132153
};
154+
} else if (!typeOf(payload, ['String', 'Array'])) {
155+
return state;
133156
} else {
134157
return {
135158
eventNameQueue: state.eventNameQueue.filter((v) => v !== payload),
@@ -142,6 +165,19 @@ function useEvent(namespace: string) {
142165
case IActionType.OFF:
143166
if (!payload) {
144167
return state;
168+
} else {
169+
return {
170+
eventNameQueue: state.eventNameQueue.filter(
171+
(v) => v !== (payload as IActionOffPayload).eventName,
172+
),
173+
eventQueue: safeRemoveEvents(
174+
[(payload as IActionOffPayload).eventName],
175+
state.eventQueue,
176+
(payload as IActionOffPayload).handler as (
177+
...args: any[]
178+
) => void,
179+
),
180+
};
145181
}
146182
case IActionType.ADD:
147183
if (
@@ -207,7 +243,7 @@ function useEvent(namespace: string) {
207243
case IActionType.ONCE:
208244
setListenerOnce(
209245
(payload as IActionAddPayload).eventName,
210-
(payload as IActionAddPayload).handler as (...args: any[]) => void,
246+
(payload as IActionAddPayload).handler as eventHandler,
211247
);
212248
return state;
213249
default:
@@ -219,33 +255,12 @@ function useEvent(namespace: string) {
219255
const [state, dispatch] = useReducer(reducer, initState);
220256

221257
const removeListener = useCallback(
222-
(eventName?: string, handler?: (...args: any[]) => void) => {
223-
// clearListener(eventName, handler);
224-
const { eventNameQueue, eventQueue } = state;
225-
if (!eventNameQueue) {
226-
console.warn('there is no event to clear');
227-
return;
228-
}
258+
(eventName?: string, handler?: eventHandler) => {
229259
const realEventName = eventName && wrapperEvent(namespace, eventName);
230-
console.log(realEventName, eventNameQueue, state);
231-
if (!realEventName || !eventNameQueue.includes(realEventName)) {
232-
console.warn(
233-
"you don't provide eventName, it will remove all listener. Thoese listeners will be remove: ",
234-
);
235-
console.table(eventQueue);
236-
}
237260

238-
if (realEventName && eventNameQueue.includes(realEventName)) {
239-
console.log('Thoese listeners will be remove: ');
240-
console.table({
241-
[eventName as string]: eventQueue[realEventName],
242-
});
243-
}
244261
dispatch({
245262
type: realEventName ? IActionType.OFF : IActionType.CLEAR,
246-
payload: realEventName
247-
? { eventName: realEventName, handlers: handler ? [handler] : [] }
248-
: null,
263+
payload: realEventName ? { eventName: realEventName, handler } : null,
249264
});
250265
},
251266
[state],

0 commit comments

Comments
 (0)