From 103d6c03fa5bb5f3415337b7626dc334175a0e50 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sat, 18 Feb 2023 11:23:38 +0100 Subject: [PATCH] feat(useEventListener): support reactive options --- packages/core/useEventListener/index.test.ts | 26 ++++++++++++++++++-- packages/core/useEventListener/index.ts | 22 ++++++++--------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/core/useEventListener/index.test.ts b/packages/core/useEventListener/index.test.ts index a98ebe4ff90..1a7bf6729bd 100644 --- a/packages/core/useEventListener/index.test.ts +++ b/packages/core/useEventListener/index.test.ts @@ -184,7 +184,7 @@ describe('useEventListener', () => { function testTarget(useTarget: boolean) { it(`should ${getTargetName(useTarget)} listen event`, async () => { - // @ts-expect-error mock different args + // @ts-expect-error mock different args const stop = useEventListener(...getArgs(useTarget)) trigger(useTarget) @@ -195,7 +195,7 @@ describe('useEventListener', () => { }) it(`should ${getTargetName(useTarget)} manually stop listening event`, async () => { - // @ts-expect-error mock different args + // @ts-expect-error mock different args const stop = useEventListener(...getArgs(useTarget)) stop() @@ -227,4 +227,26 @@ describe('useEventListener', () => { testTarget(false) testTarget(true) }) + + it('should auto re-register', async () => { + const target = ref() + const listener = vi.fn() + const options = ref(false) + useEventListener(target, 'click', listener, options) + + const el = document.createElement('div') + const addSpy = vi.spyOn(el, 'addEventListener') + const removeSpy = vi.spyOn(el, 'removeEventListener') + target.value = el + await nextTick() + expect(addSpy).toHaveBeenCalledTimes(1) + expect(addSpy).toHaveBeenLastCalledWith('click', listener, false) + expect(removeSpy).toHaveBeenCalledTimes(0) + + options.value = true + await nextTick() + expect(addSpy).toHaveBeenCalledTimes(2) + expect(addSpy).toHaveBeenLastCalledWith('click', listener, true) + expect(removeSpy).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/core/useEventListener/index.ts b/packages/core/useEventListener/index.ts index 6b7bab0e010..783ac06bb0b 100644 --- a/packages/core/useEventListener/index.ts +++ b/packages/core/useEventListener/index.ts @@ -1,5 +1,5 @@ import type { Arrayable, Fn, MaybeComputedRef } from '@vueuse/shared' -import { isString, noop, tryOnScopeDispose } from '@vueuse/shared' +import { isString, noop, resolveUnref, tryOnScopeDispose } from '@vueuse/shared' import { watch } from 'vue-demi' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' @@ -30,7 +30,7 @@ export interface GeneralEventListener { export function useEventListener( event: Arrayable, listener: Arrayable<(this: Window, ev: WindowEventMap[E]) => any>, - options?: boolean | AddEventListenerOptions + options?: MaybeComputedRef ): Fn /** @@ -48,7 +48,7 @@ export function useEventListener( target: Window, event: Arrayable, listener: Arrayable<(this: Window, ev: WindowEventMap[E]) => any>, - options?: boolean | AddEventListenerOptions + options?: MaybeComputedRef ): Fn /** @@ -66,7 +66,7 @@ export function useEventListener( target: DocumentOrShadowRoot, event: Arrayable, listener: Arrayable<(this: Document, ev: DocumentEventMap[E]) => any>, - options?: boolean | AddEventListenerOptions + options?: MaybeComputedRef ): Fn /** @@ -84,7 +84,7 @@ export function useEventListener( target: InferEventTarget, event: Arrayable, listener: Arrayable>, - options?: boolean | AddEventListenerOptions + options?: MaybeComputedRef ): Fn /** @@ -102,14 +102,14 @@ export function useEventListener( target: MaybeComputedRef, event: Arrayable, listener: Arrayable>, - options?: boolean | AddEventListenerOptions + options?: MaybeComputedRef ): Fn export function useEventListener(...args: any[]) { let target: MaybeComputedRef | undefined let events: Arrayable let listeners: Arrayable - let options: any + let options: MaybeComputedRef | undefined if (isString(args[0]) || Array.isArray(args[0])) { [events, listeners, options] = args @@ -133,21 +133,21 @@ export function useEventListener(...args: any[]) { cleanups.length = 0 } - const register = (el: any, event: string, listener: any) => { + const register = (el: any, event: string, listener: any, options: any) => { el.addEventListener(event, listener, options) return () => el.removeEventListener(event, listener, options) } const stopWatch = watch( - () => unrefElement(target as unknown as MaybeElementRef), - (el) => { + () => [unrefElement(target as unknown as MaybeElementRef), resolveUnref(options)], + ([el, options]) => { cleanup() if (!el) return cleanups.push( ...(events as string[]).flatMap((event) => { - return (listeners as Function[]).map(listener => register(el, event, listener)) + return (listeners as Function[]).map(listener => register(el, event, listener, options)) }), ) },