From 335f30c887056387f7b9eee5eb4ab28540424253 Mon Sep 17 00:00:00 2001
From: vben <anncwb@126.com>
Date: Fri, 7 Apr 2023 00:12:26 +0800
Subject: [PATCH] chore: 优化 useScrollTo、useWindowSizeFn

---
 packages/hooks/src/index.ts                              |  2 ++
 packages/hooks/src/useAttrs.ts                           |  6 +++---
 packages/hooks/src/useRefs.ts                            | 12 ++++++++++--
 packages/hooks/src/useScrollTo.ts                        | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 packages/hooks/src/useWindowSizeFn.ts                    | 40 ++++++++++++++++++++++++++++++++++++++++
 packages/types/src/utils.ts                              |  4 ++--
 src/components/Application/src/search/AppSearchModal.vue |  2 +-
 src/components/Application/src/search/useMenuSearch.ts   |  2 +-
 src/components/CodeEditor/src/codemirror/CodeMirror.vue  | 14 ++++++++++++--
 src/components/Container/src/ScrollContainer.vue         |  3 ++-
 src/components/Modal/src/components/ModalWrapper.vue     | 13 +++++++------
 src/components/Table/src/hooks/useTableScroll.ts         |  5 ++---
 src/hooks/core/useContext.ts                             |  1 -
 src/hooks/event/useScrollTo.ts                           | 59 -----------------------------------------------------------
 src/hooks/event/useWindowSizeFn.ts                       | 35 -----------------------------------
 src/hooks/web/useContentHeight.ts                        |  6 ++----
 src/hooks/web/useTitle.ts                                |  1 -
 src/layouts/default/content/useContentViewHeight.ts      |  5 ++---
 src/views/sys/iframe/index.vue                           |  4 ++--
 19 files changed, 148 insertions(+), 126 deletions(-)
 create mode 100644 packages/hooks/src/useScrollTo.ts
 create mode 100644 packages/hooks/src/useWindowSizeFn.ts
 delete mode 100644 src/hooks/event/useScrollTo.ts
 delete mode 100644 src/hooks/event/useWindowSizeFn.ts

diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts
index e18d6d9..71fb0c5 100644
--- a/packages/hooks/src/index.ts
+++ b/packages/hooks/src/index.ts
@@ -1,4 +1,6 @@
 export * from './onMountedOrActivated';
 export * from './useAttrs';
 export * from './useRefs';
+export * from './useScrollTo';
+export * from './useWindowSizeFn';
 export { useTimeoutFn } from '@vueuse/core';
diff --git a/packages/hooks/src/useAttrs.ts b/packages/hooks/src/useAttrs.ts
index c9b14ea..df2118d 100644
--- a/packages/hooks/src/useAttrs.ts
+++ b/packages/hooks/src/useAttrs.ts
@@ -1,7 +1,7 @@
 import { type Recordable } from '@vben/types';
 import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
 
-interface Options {
+interface UseAttrsOptions {
   excludeListeners?: boolean;
   excludeKeys?: string[];
   excludeDefaultKeys?: boolean;
@@ -14,7 +14,7 @@ function entries<T>(obj: Recordable<T>): [string, T][] {
   return Object.keys(obj).map((key: string) => [key, obj[key]]);
 }
 
-function useAttrs(options: Options = {}): Recordable<any> {
+function useAttrs(options: UseAttrsOptions = {}): Recordable<any> {
   const instance = getCurrentInstance();
   if (!instance) return {};
 
@@ -40,4 +40,4 @@ function useAttrs(options: Options = {}): Recordable<any> {
   return attrs;
 }
 
-export { useAttrs };
+export { useAttrs, type UseAttrsOptions };
diff --git a/packages/hooks/src/useRefs.ts b/packages/hooks/src/useRefs.ts
index 4f3faf2..97f1b4b 100644
--- a/packages/hooks/src/useRefs.ts
+++ b/packages/hooks/src/useRefs.ts
@@ -1,7 +1,10 @@
 import type { Ref } from 'vue';
 import { onBeforeUpdate, shallowRef } from 'vue';
 
-export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElement) => void] {
+function useRefs(): {
+  refs: Ref<HTMLElement[]>;
+  setRefs: (index: number) => (el: HTMLElement) => void;
+} {
   const refs = shallowRef([]) as Ref<HTMLElement[]>;
 
   onBeforeUpdate(() => {
@@ -12,5 +15,10 @@ export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElem
     refs.value[index] = el;
   };
 
-  return [refs, setRefs];
+  return {
+    refs,
+    setRefs,
+  };
 }
+
+export { useRefs };
diff --git a/packages/hooks/src/useScrollTo.ts b/packages/hooks/src/useScrollTo.ts
new file mode 100644
index 0000000..f6a95f4
--- /dev/null
+++ b/packages/hooks/src/useScrollTo.ts
@@ -0,0 +1,60 @@
+import { shallowRef, unref } from 'vue';
+
+interface UseScrollToOptions {
+  el: any;
+  to: number;
+  duration?: number;
+  callback?: () => any;
+}
+
+function easeInOutQuad(t: number, b: number, c: number, d: number) {
+  t /= d / 2;
+  if (t < 1) {
+    return (c / 2) * t * t + b;
+  }
+  t--;
+  return (-c / 2) * (t * (t - 2) - 1) + b;
+}
+
+function move(el: HTMLElement, amount: number) {
+  el.scrollTop = amount;
+}
+
+const position = (el: HTMLElement) => {
+  return el.scrollTop;
+};
+function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) {
+  const isActiveRef = shallowRef(false);
+  const start = position(el);
+  const change = to - start;
+  const increment = 20;
+  let currentTime = 0;
+
+  const animateScroll = function () {
+    if (!unref(isActiveRef)) {
+      return;
+    }
+    currentTime += increment;
+    const val = easeInOutQuad(currentTime, start, change, duration);
+    move(el, val);
+    if (currentTime < duration && unref(isActiveRef)) {
+      requestAnimationFrame(animateScroll);
+    } else {
+      if (callback && typeof callback === 'function') {
+        callback();
+      }
+    }
+  };
+  const run = () => {
+    isActiveRef.value = true;
+    animateScroll();
+  };
+
+  const stop = () => {
+    isActiveRef.value = false;
+  };
+
+  return { start: run, stop };
+}
+
+export { useScrollTo, type UseScrollToOptions };
diff --git a/packages/hooks/src/useWindowSizeFn.ts b/packages/hooks/src/useWindowSizeFn.ts
new file mode 100644
index 0000000..d8e7710
--- /dev/null
+++ b/packages/hooks/src/useWindowSizeFn.ts
@@ -0,0 +1,40 @@
+import { type AnyFunction } from '@vben/types';
+import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
+
+interface UseWindowSizeOptions {
+  wait?: number;
+  once?: boolean;
+  immediate?: boolean;
+  listenerOptions?: AddEventListenerOptions | boolean;
+}
+
+function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
+  const { wait = 150, immediate } = options;
+  let handler = () => {
+    fn();
+  };
+  const handleSize = useDebounceFn(handler, wait);
+  handler = handleSize;
+
+  const start = () => {
+    if (immediate) {
+      handler();
+    }
+    window.addEventListener('resize', handler);
+  };
+
+  const stop = () => {
+    window.removeEventListener('resize', handler);
+  };
+
+  tryOnMounted(() => {
+    start();
+  });
+
+  tryOnUnmounted(() => {
+    stop();
+  });
+  return { start, stop };
+}
+
+export { useWindowSizeFn, type UseWindowSizeOptions };
diff --git a/packages/types/src/utils.ts b/packages/types/src/utils.ts
index 73e51f5..80435fc 100644
--- a/packages/types/src/utils.ts
+++ b/packages/types/src/utils.ts
@@ -1,12 +1,12 @@
 /**
  * 任意类型的异步函数
  */
-type AnyPromiseFunction = (...arg: any) => PromiseLike<any>;
+type AnyPromiseFunction = (...arg: any[]) => PromiseLike<any>;
 
 /**
  * 任意类型的普通函数
  */
-type AnyNormalFunction = (...arg: any) => any;
+type AnyNormalFunction = (...arg: any[]) => any;
 
 /**
  * 任意类型的函数
diff --git a/src/components/Application/src/search/AppSearchModal.vue b/src/components/Application/src/search/AppSearchModal.vue
index a1546f8..612b372 100644
--- a/src/components/Application/src/search/AppSearchModal.vue
+++ b/src/components/Application/src/search/AppSearchModal.vue
@@ -81,7 +81,7 @@
 
   const { t } = useI18n();
   const { prefixCls } = useDesign('app-search-modal');
-  const [refs, setRefs] = useRefs();
+  const { refs, setRefs } = useRefs();
   const { getIsMobile } = useAppInject();
 
   const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
diff --git a/src/components/Application/src/search/useMenuSearch.ts b/src/components/Application/src/search/useMenuSearch.ts
index 1b8c71f..c938792 100644
--- a/src/components/Application/src/search/useMenuSearch.ts
+++ b/src/components/Application/src/search/useMenuSearch.ts
@@ -5,7 +5,7 @@ import { getMenus } from '/@/router/menus';
 import { cloneDeep } from 'lodash-es';
 import { filter, forEach } from '/@/utils/helper/treeHelper';
 import { useGo } from '/@/hooks/web/usePage';
-import { useScrollTo } from '/@/hooks/event/useScrollTo';
+import { useScrollTo } from '@vben/hooks';
 import { onKeyStroke, useDebounceFn } from '@vueuse/core';
 import { useI18n } from '/@/hooks/web/useI18n';
 
diff --git a/src/components/CodeEditor/src/codemirror/CodeMirror.vue b/src/components/CodeEditor/src/codemirror/CodeMirror.vue
index 426ac36..af3017f 100644
--- a/src/components/CodeEditor/src/codemirror/CodeMirror.vue
+++ b/src/components/CodeEditor/src/codemirror/CodeMirror.vue
@@ -3,10 +3,20 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref, onMounted, onUnmounted, watchEffect, watch, unref, nextTick } from 'vue';
+  import {
+    type PropType,
+    ref,
+    onMounted,
+    onUnmounted,
+    watchEffect,
+    watch,
+    unref,
+    nextTick,
+  } from 'vue';
+  import type { Nullable } from '@vben/types';
+  import { useWindowSizeFn } from '@vben/hooks';
   import { useDebounceFn } from '@vueuse/core';
   import { useAppStore } from '/@/store/modules/app';
-  import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
   import CodeMirror from 'codemirror';
   import { MODE } from './../typing';
   // css
diff --git a/src/components/Container/src/ScrollContainer.vue b/src/components/Container/src/ScrollContainer.vue
index 65c71ed..ca19003 100644
--- a/src/components/Container/src/ScrollContainer.vue
+++ b/src/components/Container/src/ScrollContainer.vue
@@ -7,7 +7,8 @@
 <script lang="ts">
   import { defineComponent, ref, unref, nextTick } from 'vue';
   import { Scrollbar, ScrollbarType } from '/@/components/Scrollbar';
-  import { useScrollTo } from '/@/hooks/event/useScrollTo';
+  import { useScrollTo } from '@vben/hooks';
+  import { type Nullable } from '@vben/types';
 
   export default defineComponent({
     name: 'ScrollContainer',
diff --git a/src/components/Modal/src/components/ModalWrapper.vue b/src/components/Modal/src/components/ModalWrapper.vue
index 699bf9c..037538c 100644
--- a/src/components/Modal/src/components/ModalWrapper.vue
+++ b/src/components/Modal/src/components/ModalWrapper.vue
@@ -18,7 +18,8 @@
     nextTick,
     onUnmounted,
   } from 'vue';
-  import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
+  import { useWindowSizeFn } from '@vben/hooks';
+  import { type AnyFunction } from '@vben/types';
   import { ScrollContainer } from '/@/components/Container';
   import { createModalContext } from '../hooks/useModalContext';
   import { useMutationObserver } from '@vueuse/core';
@@ -43,14 +44,14 @@
     props,
     emits: ['height-change', 'ext-height'],
     setup(props, { emit }) {
-      const wrapperRef = ref<ComponentRef>(null);
-      const spinRef = ref<ElRef>(null);
+      const wrapperRef = ref(null);
+      const spinRef = ref(null);
       const realHeightRef = ref(0);
       const minRealHeightRef = ref(0);
 
       let realHeight = 0;
 
-      let stopElResizeFn: Fn = () => {};
+      let stopElResizeFn: AnyFunction = () => {};
 
       useWindowSizeFn(setModalHeight.bind(null, false));
 
@@ -116,7 +117,7 @@
         const wrapperRefDom = unref(wrapperRef);
         if (!wrapperRefDom) return;
 
-        const bodyDom = wrapperRefDom.$el.parentElement;
+        const bodyDom = (wrapperRefDom as any).$el.parentElement;
         if (!bodyDom) return;
         bodyDom.style.padding = '0';
         await nextTick();
@@ -139,7 +140,7 @@
             maxHeight -= 26;
           }
           await nextTick();
-          const spinEl = unref(spinRef);
+          const spinEl: any = unref(spinRef);
 
           if (!spinEl) return;
           await nextTick();
diff --git a/src/components/Table/src/hooks/useTableScroll.ts b/src/components/Table/src/hooks/useTableScroll.ts
index c4ecf1e..3777d6e 100644
--- a/src/components/Table/src/hooks/useTableScroll.ts
+++ b/src/components/Table/src/hooks/useTableScroll.ts
@@ -2,9 +2,8 @@ import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/t
 import { Ref, ComputedRef, ref, computed, unref, nextTick, watch } from 'vue';
 import { getViewportOffset } from '/@/utils/domUtils';
 import { isBoolean } from '/@/utils/is';
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
+import { useWindowSizeFn, onMountedOrActivated } from '@vben/hooks';
 import { useModalContext } from '/@/components/Modal';
-import { onMountedOrActivated } from '@vben/hooks';
 import { useDebounceFn } from '@vueuse/core';
 
 export function useTableScroll(
@@ -171,7 +170,7 @@ export function useTableScroll(
 
     bodyEl!.style.height = `${height}px`;
   }
-  useWindowSizeFn(calcTableHeight, 280);
+  useWindowSizeFn(calcTableHeight, { wait: 280 });
   onMountedOrActivated(() => {
     calcTableHeight();
     nextTick(() => {
diff --git a/src/hooks/core/useContext.ts b/src/hooks/core/useContext.ts
index c686187..2729526 100644
--- a/src/hooks/core/useContext.ts
+++ b/src/hooks/core/useContext.ts
@@ -4,7 +4,6 @@ import {
   inject,
   reactive,
   readonly as defineReadonly,
-  // defineComponent,
   UnwrapRef,
 } from 'vue';
 
diff --git a/src/hooks/event/useScrollTo.ts b/src/hooks/event/useScrollTo.ts
deleted file mode 100644
index f6d5dc6..0000000
--- a/src/hooks/event/useScrollTo.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { isFunction, isUnDef } from '/@/utils/is';
-import { ref, unref } from 'vue';
-
-export interface ScrollToParams {
-  el: any;
-  to: number;
-  duration?: number;
-  callback?: () => any;
-}
-
-const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
-  t /= d / 2;
-  if (t < 1) {
-    return (c / 2) * t * t + b;
-  }
-  t--;
-  return (-c / 2) * (t * (t - 2) - 1) + b;
-};
-const move = (el: HTMLElement, amount: number) => {
-  el.scrollTop = amount;
-};
-
-const position = (el: HTMLElement) => {
-  return el.scrollTop;
-};
-export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams) {
-  const isActiveRef = ref(false);
-  const start = position(el);
-  const change = to - start;
-  const increment = 20;
-  let currentTime = 0;
-  duration = isUnDef(duration) ? 500 : duration;
-
-  const animateScroll = function () {
-    if (!unref(isActiveRef)) {
-      return;
-    }
-    currentTime += increment;
-    const val = easeInOutQuad(currentTime, start, change, duration);
-    move(el, val);
-    if (currentTime < duration && unref(isActiveRef)) {
-      requestAnimationFrame(animateScroll);
-    } else {
-      if (callback && isFunction(callback)) {
-        callback();
-      }
-    }
-  };
-  const run = () => {
-    isActiveRef.value = true;
-    animateScroll();
-  };
-
-  const stop = () => {
-    isActiveRef.value = false;
-  };
-
-  return { start: run, stop };
-}
diff --git a/src/hooks/event/useWindowSizeFn.ts b/src/hooks/event/useWindowSizeFn.ts
deleted file mode 100644
index 01cdc75..0000000
--- a/src/hooks/event/useWindowSizeFn.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
-
-interface WindowSizeOptions {
-  once?: boolean;
-  immediate?: boolean;
-  listenerOptions?: AddEventListenerOptions | boolean;
-}
-
-export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOptions) {
-  let handler = () => {
-    fn();
-  };
-  const handleSize = useDebounceFn(handler, wait);
-  handler = handleSize;
-
-  const start = () => {
-    if (options && options.immediate) {
-      handler();
-    }
-    window.addEventListener('resize', handler);
-  };
-
-  const stop = () => {
-    window.removeEventListener('resize', handler);
-  };
-
-  tryOnMounted(() => {
-    start();
-  });
-
-  tryOnUnmounted(() => {
-    stop();
-  });
-  return [start, stop];
-}
diff --git a/src/hooks/web/useContentHeight.ts b/src/hooks/web/useContentHeight.ts
index 53fe0ef..558cd51 100644
--- a/src/hooks/web/useContentHeight.ts
+++ b/src/hooks/web/useContentHeight.ts
@@ -1,6 +1,5 @@
 import { ComputedRef, isRef, nextTick, Ref, ref, unref, watch } from 'vue';
-import { onMountedOrActivated } from '@vben/hooks';
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
+import { onMountedOrActivated, useWindowSizeFn } from '@vben/hooks';
 import { useLayoutHeight } from '/@/layouts/default/content/useContentViewHeight';
 import { getViewportOffset } from '/@/utils/domUtils';
 import { isNumber, isString } from '/@/utils/is';
@@ -173,8 +172,7 @@ export function useContentHeight(
     () => {
       calcContentHeight();
     },
-    50,
-    { immediate: true },
+    { wait: 50, immediate: true },
   );
   watch(
     () => [layoutFooterHeightRef.value],
diff --git a/src/hooks/web/useTitle.ts b/src/hooks/web/useTitle.ts
index a7f48d8..675a5db 100644
--- a/src/hooks/web/useTitle.ts
+++ b/src/hooks/web/useTitle.ts
@@ -4,7 +4,6 @@ import { useTitle as usePageTitle } from '@vueuse/core';
 import { useGlobSetting } from '/@/hooks/setting';
 import { useRouter } from 'vue-router';
 import { useLocaleStore } from '/@/store/modules/locale';
-
 import { REDIRECT_NAME } from '/@/router/constant';
 
 /**
diff --git a/src/layouts/default/content/useContentViewHeight.ts b/src/layouts/default/content/useContentViewHeight.ts
index f620a33..8dd63fa 100644
--- a/src/layouts/default/content/useContentViewHeight.ts
+++ b/src/layouts/default/content/useContentViewHeight.ts
@@ -1,6 +1,6 @@
 import { ref, computed, unref } from 'vue';
 import { createPageContext } from '/@/hooks/component/usePageContext';
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
+import { useWindowSizeFn } from '@vben/hooks';
 
 const headerHeightRef = ref(0);
 const footerHeightRef = ref(0);
@@ -26,8 +26,7 @@ export function useContentViewHeight() {
     () => {
       contentHeight.value = window.innerHeight;
     },
-    100,
-    { immediate: true },
+    { wait: 100, immediate: true },
   );
 
   async function setPageHeight(height: number) {
diff --git a/src/views/sys/iframe/index.vue b/src/views/sys/iframe/index.vue
index 8e9129e..ebf9fc4 100644
--- a/src/views/sys/iframe/index.vue
+++ b/src/views/sys/iframe/index.vue
@@ -14,7 +14,7 @@
   import type { CSSProperties } from 'vue';
   import { ref, unref, computed } from 'vue';
   import { Spin } from 'ant-design-vue';
-  import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
+  import { useWindowSizeFn } from '@vben/hooks';
   import { propTypes } from '/@/utils/propTypes';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { useLayoutHeight } from '/@/layouts/default/content/useContentViewHeight';
@@ -30,7 +30,7 @@
   const { headerHeightRef } = useLayoutHeight();
 
   const { prefixCls } = useDesign('iframe-page');
-  useWindowSizeFn(calcHeight, 150, { immediate: true });
+  useWindowSizeFn(calcHeight, { wait: 150, immediate: true });
 
   const getWrapStyle = computed((): CSSProperties => {
     return {
--
libgit2 0.23.3