1
1
import { useCallback , useContext , useReducer } from 'react' ;
2
2
import { context , wrapperEvent } from '../context' ;
3
+ import { typeOf } from '../utils/tool' ;
4
+
5
+ export type eventHandler = ( ...args : any [ ] ) => void ;
3
6
4
7
export interface IEventQueue {
5
- [ _ : string ] : ( ( ... args : any [ ] ) => void ) [ ] ;
8
+ [ _ : string ] : eventHandler [ ] ;
6
9
}
7
-
8
10
export interface IActionAddPayload {
9
11
eventName : string ;
10
- handlers : ( ( ... args : any [ ] ) => void ) [ ] ;
11
- handler ?: ( ... args : any [ ] ) => void ;
12
+ handlers : eventHandler [ ] ;
13
+ handler ?: eventHandler ;
12
14
params ?: any [ ] ;
13
15
}
14
16
export interface IActionTriggerPayload {
15
17
eventName : string ;
16
18
params : any [ ] ;
17
19
}
20
+
21
+ export interface IActionOffPayload {
22
+ eventName : string ;
23
+ handler ?: eventHandler ;
24
+ }
25
+
18
26
export interface IState {
19
27
eventQueue : IEventQueue ;
20
28
eventNameQueue : string [ ] ;
@@ -31,13 +39,17 @@ export enum IActionType {
31
39
32
40
export interface IAction {
33
41
type : IActionType ;
34
- payload : string | string [ ] | IActionAddPayload | IActionTriggerPayload | null ;
42
+ payload :
43
+ | string
44
+ | string [ ]
45
+ | IActionAddPayload
46
+ | IActionTriggerPayload
47
+ | IActionOffPayload
48
+ | null ;
35
49
}
36
50
37
51
export const safeNamespace = [ '__taro' , 'at' ] ;
38
52
39
- declare function sideEffectHandler < U extends any [ ] > ( ...args : U ) : void ;
40
-
41
53
const initState : IState = {
42
54
eventQueue : { } ,
43
55
eventNameQueue : [ ] ,
@@ -47,7 +59,7 @@ function useEvent(namespace: string) {
47
59
const { eventBus } = useContext ( context ) ;
48
60
49
61
const setListener = useCallback (
50
- ( eventName : string , ...handlers : ( ( ... args : any [ ] ) => void ) [ ] ) => {
62
+ ( eventName : string , ...handlers : eventHandler [ ] ) => {
51
63
if ( ! eventName || safeNamespace . some ( ( v ) => eventName . startsWith ( v ) ) ) {
52
64
console . warn ( 'eventName not valid. listen failed' ) ;
53
65
} else if ( ! handlers . length ) {
@@ -66,7 +78,7 @@ function useEvent(namespace: string) {
66
78
) ;
67
79
68
80
const setListenerOnce = useCallback (
69
- ( eventName : string , handler : ( ... args : any [ ] ) => void ) => {
81
+ ( eventName : string , handler : eventHandler ) => {
70
82
if ( ! eventName || ! handler ) {
71
83
console . warn ( 'you must provide eventName and handler' ) ;
72
84
return ;
@@ -101,16 +113,25 @@ function useEvent(namespace: string) {
101
113
} , [ ] ) ;
102
114
103
115
const safeRemoveEvents = useCallback (
104
- ( eventNameQueue : string [ ] , eventQueue ) : IEventQueue => {
116
+ (
117
+ eventNameQueue : string [ ] ,
118
+ eventQueue ,
119
+ ...handlers : eventHandler [ ]
120
+ ) : IEventQueue => {
105
121
const removeEventName = eventNameQueue . filter (
106
122
( v ) => ! safeNamespace . some ( ( n ) => v . startsWith ( n ) ) ,
107
123
) ;
108
124
109
- removeEventName . forEach ( ( v ) => eventBus . off ( v ) ) ;
125
+ removeEventName . forEach ( ( v ) => eventBus . off ( v , ... ( handlers || [ ] ) ) ) ;
110
126
const offQueue : IEventQueue = { } ;
111
127
if ( eventNameQueue . length === 1 && removeEventName . length ) {
112
128
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 ) ) {
114
135
offQueue [ key ] = eventQueue [ key ] ;
115
136
}
116
137
} ) ;
@@ -130,6 +151,8 @@ function useEvent(namespace: string) {
130
151
eventQueue : { } ,
131
152
eventNameQueue : [ ] ,
132
153
} ;
154
+ } else if ( ! typeOf ( payload , [ 'String' , 'Array' ] ) ) {
155
+ return state ;
133
156
} else {
134
157
return {
135
158
eventNameQueue : state . eventNameQueue . filter ( ( v ) => v !== payload ) ,
@@ -142,6 +165,19 @@ function useEvent(namespace: string) {
142
165
case IActionType . OFF :
143
166
if ( ! payload ) {
144
167
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
+ } ;
145
181
}
146
182
case IActionType . ADD :
147
183
if (
@@ -207,7 +243,7 @@ function useEvent(namespace: string) {
207
243
case IActionType . ONCE :
208
244
setListenerOnce (
209
245
( payload as IActionAddPayload ) . eventName ,
210
- ( payload as IActionAddPayload ) . handler as ( ... args : any [ ] ) => void ,
246
+ ( payload as IActionAddPayload ) . handler as eventHandler ,
211
247
) ;
212
248
return state ;
213
249
default :
@@ -219,33 +255,12 @@ function useEvent(namespace: string) {
219
255
const [ state , dispatch ] = useReducer ( reducer , initState ) ;
220
256
221
257
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 ) => {
229
259
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
- }
237
260
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
- }
244
261
dispatch ( {
245
262
type : realEventName ? IActionType . OFF : IActionType . CLEAR ,
246
- payload : realEventName
247
- ? { eventName : realEventName , handlers : handler ? [ handler ] : [ ] }
248
- : null ,
263
+ payload : realEventName ? { eventName : realEventName , handler } : null ,
249
264
} ) ;
250
265
} ,
251
266
[ state ] ,
0 commit comments