useEventListener.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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({
  15. el = window,
  16. name,
  17. listener,
  18. options,
  19. autoRemove = true,
  20. isDebounce = true,
  21. wait = 80
  22. }: UseEventParams): { removeEvent: RemoveEventFn } {
  23. /* eslint-disable-next-line */
  24. let remove: RemoveEventFn = () => {};
  25. const isAddRef = ref(false);
  26. if (el) {
  27. const element = ref<Element>(el);
  28. // eslint-disable-next-line prettier/prettier
  29. const handler = isDebounce
  30. ? useDebounceFn(listener, wait)
  31. : useThrottleFn(listener, wait);
  32. const realHandler = wait ? handler : listener;
  33. const removeEventListener = (e: Element) => {
  34. isAddRef.value = true;
  35. e.removeEventListener(name, realHandler, options);
  36. };
  37. // eslint-disable-next-line prettier/prettier
  38. const addEventListener = (e: Element) =>
  39. e.addEventListener(name, realHandler, options);
  40. const removeWatch = watch(
  41. element,
  42. (v, _ov, cleanUp) => {
  43. if (v) {
  44. !unref(isAddRef) && addEventListener(v as unknown as Element);
  45. cleanUp(() => {
  46. autoRemove && removeEventListener(v as unknown as Element);
  47. });
  48. }
  49. },
  50. { immediate: true }
  51. );
  52. remove = () => {
  53. removeEventListener(element.value as unknown as Element);
  54. removeWatch();
  55. };
  56. }
  57. return { removeEvent: remove };
  58. }