1
- import type { Arrayable , Fn , MaybeRefOrGetter } from '@vueuse/shared'
2
- import type { MaybeElementRef } from '../unrefElement '
3
- import { isObject , noop , toArray , tryOnScopeDispose } from '@vueuse/shared'
4
- import { toValue , watch } from 'vue'
1
+ import type { Arrayable , Fn , MaybeRef , MaybeRefOrGetter } from '@vueuse/shared'
2
+ import { isObject , toArray , tryOnScopeDispose , watchImmediate } from '@vueuse/shared '
3
+ // eslint-disable-next-line no-restricted-imports -- We specifically need to use unref here to distinguish between callbacks
4
+ import { computed , toValue , unref } from 'vue'
5
5
import { defaultWindow } from '../_configurable'
6
6
import { unrefElement } from '../unrefElement'
7
7
@@ -27,9 +27,10 @@ export interface GeneralEventListener<E = Event> {
27
27
* @param listener
28
28
* @param options
29
29
*/
30
+ // @ts -expect-error - TypeScript gets confused with this and can't infer the correct overload with Parameters<...>
30
31
export function useEventListener < E extends keyof WindowEventMap > (
31
- event : Arrayable < E > ,
32
- listener : Arrayable < ( this : Window , ev : WindowEventMap [ E ] ) => any > ,
32
+ event : MaybeRefOrGetter < Arrayable < E > > ,
33
+ listener : MaybeRef < Arrayable < ( this : Window , ev : WindowEventMap [ E ] ) => any > > ,
33
34
options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
34
35
) : Fn
35
36
@@ -46,8 +47,8 @@ export function useEventListener<E extends keyof WindowEventMap>(
46
47
*/
47
48
export function useEventListener < E extends keyof WindowEventMap > (
48
49
target : Window ,
49
- event : Arrayable < E > ,
50
- listener : Arrayable < ( this : Window , ev : WindowEventMap [ E ] ) => any > ,
50
+ event : MaybeRefOrGetter < Arrayable < E > > ,
51
+ listener : MaybeRef < Arrayable < ( this : Window , ev : WindowEventMap [ E ] ) => any > > ,
51
52
options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
52
53
) : Fn
53
54
@@ -64,8 +65,8 @@ export function useEventListener<E extends keyof WindowEventMap>(
64
65
*/
65
66
export function useEventListener < E extends keyof DocumentEventMap > (
66
67
target : DocumentOrShadowRoot ,
67
- event : Arrayable < E > ,
68
- listener : Arrayable < ( this : Document , ev : DocumentEventMap [ E ] ) => any > ,
68
+ event : MaybeRefOrGetter < Arrayable < E > > ,
69
+ listener : MaybeRef < Arrayable < ( this : Document , ev : DocumentEventMap [ E ] ) => any > > ,
69
70
options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
70
71
) : Fn
71
72
@@ -81,10 +82,10 @@ export function useEventListener<E extends keyof DocumentEventMap>(
81
82
* @param options
82
83
*/
83
84
export function useEventListener < E extends keyof HTMLElementEventMap > (
84
- target : MaybeRefOrGetter < HTMLElement | null | undefined > ,
85
- event : Arrayable < E > ,
86
- listener : ( this : HTMLElement , ev : HTMLElementEventMap [ E ] ) => any ,
87
- options ?: boolean | AddEventListenerOptions
85
+ target : MaybeRefOrGetter < Arrayable < HTMLElement > | null | undefined > ,
86
+ event : MaybeRefOrGetter < Arrayable < E > > ,
87
+ listener : MaybeRef < ( this : HTMLElement , ev : HTMLElementEventMap [ E ] ) => any > ,
88
+ options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
88
89
) : ( ) => void
89
90
90
91
/**
@@ -99,9 +100,9 @@ export function useEventListener<E extends keyof HTMLElementEventMap>(
99
100
* @param options
100
101
*/
101
102
export function useEventListener < Names extends string , EventType = Event > (
102
- target : MaybeRefOrGetter < InferEventTarget < Names > | null | undefined > ,
103
- event : Arrayable < Names > ,
104
- listener : Arrayable < GeneralEventListener < EventType > > ,
103
+ target : MaybeRefOrGetter < Arrayable < InferEventTarget < Names > > | null | undefined > ,
104
+ event : MaybeRefOrGetter < Arrayable < Names > > ,
105
+ listener : MaybeRef < Arrayable < GeneralEventListener < EventType > > > ,
105
106
options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
106
107
) : Fn
107
108
@@ -117,67 +118,67 @@ export function useEventListener<Names extends string, EventType = Event>(
117
118
* @param options
118
119
*/
119
120
export function useEventListener < EventType = Event > (
120
- target : MaybeRefOrGetter < EventTarget | null | undefined > ,
121
- event : Arrayable < string > ,
122
- listener : Arrayable < GeneralEventListener < EventType > > ,
121
+ target : MaybeRefOrGetter < Arrayable < EventTarget > | null | undefined > ,
122
+ event : MaybeRefOrGetter < Arrayable < string > > ,
123
+ listener : MaybeRef < Arrayable < GeneralEventListener < EventType > > > ,
123
124
options ?: MaybeRefOrGetter < boolean | AddEventListenerOptions >
124
125
) : Fn
125
126
126
- export function useEventListener ( ...args : any [ ] ) {
127
- let target : MaybeRefOrGetter < EventTarget > | undefined
128
- let events : Arrayable < string >
129
- let listeners : Arrayable < Function >
130
- let options : MaybeRefOrGetter < boolean | AddEventListenerOptions > | undefined
131
-
132
- if ( typeof args [ 0 ] === 'string' || Array . isArray ( args [ 0 ] ) ) {
133
- [ events , listeners , options ] = args
134
- target = defaultWindow
135
- }
136
- else {
137
- [ target , events , listeners , options ] = args
138
- }
139
-
140
- if ( ! target )
141
- return noop
142
-
143
- events = toArray ( events )
144
- listeners = toArray ( listeners )
145
-
127
+ export function useEventListener ( ...args : Parameters < typeof useEventListener > ) {
146
128
const cleanups : Function [ ] = [ ]
147
129
const cleanup = ( ) => {
148
130
cleanups . forEach ( fn => fn ( ) )
149
131
cleanups . length = 0
150
132
}
151
133
152
- const register = ( el : any , event : string , listener : any , options : any ) => {
134
+ const register = (
135
+ el : EventTarget ,
136
+ event : string ,
137
+ listener : any ,
138
+ options : boolean | AddEventListenerOptions | undefined ,
139
+ ) => {
153
140
el . addEventListener ( event , listener , options )
154
141
return ( ) => el . removeEventListener ( event , listener , options )
155
142
}
156
143
157
- const stopWatch = watch (
158
- ( ) => [ unrefElement ( target as unknown as MaybeElementRef ) , toValue ( options ) ] ,
159
- ( [ el , options ] ) => {
144
+ const firstParamTargets = computed ( ( ) => {
145
+ const test = toArray ( toValue ( args [ 0 ] ) ) . filter ( e => e != null )
146
+ return test . every ( e => typeof e !== 'string' ) ? test : undefined
147
+ } )
148
+
149
+ const stopWatch = watchImmediate (
150
+ ( ) => [
151
+ firstParamTargets . value ?. map ( e => unrefElement ( e as never ) ) ?? [ defaultWindow ] . filter ( e => e != null ) ,
152
+ toArray ( toValue ( firstParamTargets . value ? args [ 1 ] : args [ 0 ] ) ) as unknown as string [ ] ,
153
+ toArray ( unref ( firstParamTargets . value ? args [ 2 ] : args [ 1 ] ) ) as Function [ ] ,
154
+ // @ts -expect-error - TypeScript gets the correct types, but somehow still complains
155
+ toValue ( firstParamTargets . value ? args [ 3 ] : args [ 2 ] ) as boolean | AddEventListenerOptions | undefined ,
156
+ ] as const ,
157
+ ( [ raw_targets , raw_events , raw_listeners , raw_options ] ) => {
160
158
cleanup ( )
161
- if ( ! el )
159
+
160
+ if ( ! raw_targets ?. length || ! raw_events ?. length || ! raw_listeners ?. length )
162
161
return
163
162
164
163
// create a clone of options, to avoid it being changed reactively on removal
165
- const optionsClone = isObject ( options ) ? { ...options } : options
164
+ const optionsClone = isObject ( raw_options ) ? { ...raw_options } : raw_options
166
165
cleanups . push (
167
- ...( events as string [ ] ) . flatMap ( ( event ) => {
168
- return ( listeners as Function [ ] ) . map ( listener => register ( el , event , listener , optionsClone ) )
169
- } ) ,
166
+ ...raw_targets . flatMap ( el =>
167
+ raw_events . flatMap ( event =>
168
+ raw_listeners . map ( listener => register ( el , event , listener , optionsClone ) ) ,
169
+ ) ,
170
+ ) ,
170
171
)
171
172
} ,
172
- { immediate : true , flush : 'post' } ,
173
+ { flush : 'post' } ,
173
174
)
174
175
175
176
const stop = ( ) => {
176
177
stopWatch ( )
177
178
cleanup ( )
178
179
}
179
180
180
- tryOnScopeDispose ( stop )
181
+ tryOnScopeDispose ( cleanup )
181
182
182
183
return stop
183
184
}
0 commit comments