useEventListener.ts 1.6 KB

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