useEventListener.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import type { Ref } from 'vue';
  2. import { ref, watch, unref } from 'vue';
  3. import { useThrottleFn, useDebounceFn } from '@vueuse/core';
  4. export type RemoveEventFn = () => void;
  5. export interface UseEventParams {
  6. el?: Element | Ref<Element | undefined> | Window | any;
  7. name: string;
  8. listener: EventListener;
  9. options?: boolean | AddEventListenerOptions;
  10. autoRemove?: boolean;
  11. isDebounce?: boolean;
  12. wait?: number;
  13. }
  14. export function useEventListener({ el = window, name, listener, options, autoRemove = true, isDebounce = true, wait = 80 }: UseEventParams): {
  15. removeEvent: RemoveEventFn;
  16. } {
  17. /* eslint-disable-next-line */
  18. let remove: RemoveEventFn = () => {};
  19. const isAddRef = ref(false);
  20. if (el) {
  21. const element = ref(el as Element) as Ref<Element>;
  22. const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait);
  23. const realHandler = wait ? handler : listener;
  24. const removeEventListener = (e: Element) => {
  25. isAddRef.value = true;
  26. e.removeEventListener(name, realHandler, options);
  27. };
  28. const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options);
  29. const removeWatch = watch(
  30. element,
  31. (v, _ov, cleanUp) => {
  32. if (v) {
  33. !unref(isAddRef) && addEventListener(v);
  34. cleanUp(() => {
  35. autoRemove && removeEventListener(v);
  36. });
  37. }
  38. },
  39. { immediate: true }
  40. );
  41. remove = () => {
  42. removeEventListener(element.value);
  43. removeWatch();
  44. };
  45. }
  46. return { removeEvent: remove };
  47. }