You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
1.7 KiB

  1. import {
  2. isFunction,
  3. isObject,
  4. isArray,
  5. debounce,
  6. throttle
  7. } from "@pureadmin/utils";
  8. import { useEventListener } from "@vueuse/core";
  9. import type { Directive, DirectiveBinding } from "vue";
  10. /** 防抖(v-optimize或v-optimize:debounce)、节流(v-optimize:throttle)指令 */
  11. export const optimize: Directive = {
  12. mounted(el: HTMLElement, binding: DirectiveBinding) {
  13. const { value } = binding;
  14. const optimizeType = binding.arg ?? "debounce";
  15. const type = ["debounce", "throttle"].find(t => t === optimizeType);
  16. if (type) {
  17. if (value && value.event && isFunction(value.fn)) {
  18. let params = value?.params;
  19. if (params) {
  20. if (isArray(params) || isObject(params)) {
  21. params = isObject(params) ? Array.of(params) : params;
  22. } else {
  23. throw new Error(
  24. "[Directive: optimize]: `params` must be an array or object"
  25. );
  26. }
  27. }
  28. // Register using addEventListener on mounted, and removeEventListener automatically on unmounted
  29. useEventListener(
  30. el,
  31. value.event,
  32. type === "debounce"
  33. ? debounce(
  34. params ? () => value.fn(...params) : value.fn,
  35. value?.timeout ?? 200,
  36. value?.immediate ?? false
  37. )
  38. : throttle(
  39. params ? () => value.fn(...params) : value.fn,
  40. value?.timeout ?? 1000
  41. )
  42. );
  43. } else {
  44. throw new Error(
  45. "[Directive: optimize]: `event` and `fn` are required, and `fn` must be a function"
  46. );
  47. }
  48. } else {
  49. throw new Error(
  50. "[Directive: optimize]: only `debounce` and `throttle` are supported"
  51. );
  52. }
  53. }
  54. };