瀏覽代碼

refactor(hooks): introduce vueuse, delete duplicate hooks

vben 4 年之前
父節點
當前提交
d9b1960030
共有 48 個文件被更改,包括 135 次插入610 次删除
  1. 6 0
      CHANGELOG.zh_CN.md
  2. 1 0
      package.json
  3. 1 3
      src/App.vue
  4. 2 2
      src/components/Breadcrumb/BreadcrumbItem.vue
  5. 3 4
      src/components/Container/src/LazyContainer.vue
  6. 3 2
      src/components/Container/src/collapse/CollapseContainer.vue
  7. 1 3
      src/components/CountTo/src/index.vue
  8. 2 2
      src/components/Modal/src/Modal.tsx
  9. 1 13
      src/components/Modal/src/ModalWrapper.tsx
  10. 2 2
      src/components/Table/src/BasicTable.vue
  11. 2 2
      src/components/Table/src/hooks/useDataSource.ts
  12. 1 12
      src/components/Table/src/hooks/useTableScroll.ts
  13. 4 4
      src/components/Verify/src/DragVerify.tsx
  14. 2 2
      src/components/Verify/src/ImgRotate.tsx
  15. 2 2
      src/components/Verify/src/VerifyModal.vue
  16. 2 2
      src/components/VirtualScroll/src/index.tsx
  17. 0 56
      src/hooks/core/asyncComputed.ts
  18. 0 16
      src/hooks/core/useCounter.ts
  19. 0 23
      src/hooks/core/useTimeout.ts
  20. 0 24
      src/hooks/core/useTimeoutRef.ts
  21. 6 6
      src/hooks/event/useBreakpoint.ts
  22. 0 10
      src/hooks/event/useEventHub.ts
  23. 1 1
      src/hooks/event/useEventListener.ts
  24. 0 48
      src/hooks/event/useIntersectionObserver.ts
  25. 0 35
      src/hooks/event/useNow.ts
  26. 0 95
      src/hooks/event/useRaf.ts
  27. 2 2
      src/hooks/event/useScrollTo.ts
  28. 0 20
      src/hooks/event/useWindowSizeFn.ts
  29. 0 12
      src/hooks/state/useGlobalState.ts
  30. 2 2
      src/hooks/web/useApexCharts.ts
  31. 3 3
      src/hooks/web/useClickOutside.ts
  32. 0 40
      src/hooks/web/useCssVar.ts
  33. 5 5
      src/hooks/web/useECharts.ts
  34. 0 5
      src/hooks/web/useLocalStorage.ts
  35. 0 53
      src/hooks/web/useNetWork.ts
  36. 0 5
      src/hooks/web/useSessionStorage.ts
  37. 2 2
      src/hooks/web/useTabs.ts
  38. 0 32
      src/hooks/web/useTitle.ts
  39. 0 20
      src/hooks/web/useVisibilityState.ts
  40. 1 1
      src/layouts/default/header/LayoutHeader.tsx
  41. 2 2
      src/layouts/logo/index.vue
  42. 0 3
      src/settings/projectSetting.ts
  43. 4 1
      src/setup/theme/index.ts
  44. 0 2
      src/types/config.d.ts
  45. 0 30
      src/useApp.ts
  46. 51 0
      src/utils/animation.ts
  47. 1 1
      src/views/sys/iframe/index.vue
  48. 20 0
      yarn.lock

+ 6 - 0
CHANGELOG.zh_CN.md

@@ -1,5 +1,10 @@
 ## Wip
 
+### ✨ Refactor
+
+- 重构 hook,引入 `@vueuse`,删除其中已有的`hook`,优化现有的 hook
+- `useEvent` 更名->`useEventListener`
+
 ### ✨ Features
 
 - 表单项的`componentsProps`支持函数类型
@@ -16,6 +21,7 @@
 - 修复多个富文本编辑器只显示一个
 - 修复登录过期后重新登录未跳转原来页面的
 - 修复 window 系统动态引入错误
+- 修复页面类型错误
 
 ## 2.0.0-rc.9 (2020-11-9)
 

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
   },
   "dependencies": {
     "@iconify/iconify": "^2.0.0-rc.2",
+    "@vueuse/core": "^4.0.0-beta.40",
     "ant-design-vue": "^2.0.0-beta.15",
     "apexcharts": "3.22.0",
     "axios": "^0.21.0",

+ 1 - 3
src/App.vue

@@ -13,7 +13,7 @@
   import moment from 'moment';
   import 'moment/dist/locale/zh-cn';
 
-  import { useConfigProvider, useInitAppConfigStore, useListenerNetWork } from './useApp';
+  import { useConfigProvider, useInitAppConfigStore } from './useApp';
   import { useLockPage } from '/@/hooks/web/useLockPage';
   import { useSetting } from '/@/hooks/core/useSetting';
 
@@ -25,8 +25,6 @@
     setup() {
       // Initialize application settings
       useInitAppConfigStore();
-      // Initialize network monitoring
-      useListenerNetWork();
       // Initialize breakpoint monitoring
       createBreakpointListen();
       // Get system configuration

+ 2 - 2
src/components/Breadcrumb/BreadcrumbItem.vue

@@ -11,7 +11,7 @@
 <script lang="ts">
   import { defineComponent, inject, ref, onMounted, unref } from 'vue';
   import { useRouter } from 'vue-router';
-  import { useEvent } from '/@/hooks/event/useEvent';
+  import { useEventListener } from '/@/hooks/event/useEventListener';
 
   export default defineComponent({
     name: 'BreadcrumbItem',
@@ -42,7 +42,7 @@
       onMounted(() => {
         const link = unref(linkRef);
         if (!link) return;
-        useEvent({
+        useEventListener({
           el: link,
           listener: () => {
             const { to } = props;

+ 3 - 4
src/components/Container/src/LazyContainer.vue

@@ -22,8 +22,7 @@
   import { defineComponent, reactive, onMounted, ref, toRef, toRefs } from 'vue';
 
   import { Skeleton } from 'ant-design-vue';
-  import { useTimeout } from '/@/hooks/core/useTimeout';
-  import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver';
+  import { useTimeoutFn, useIntersectionObserver } from '@vueuse/core';
   interface State {
     isInit: boolean;
     loading: boolean;
@@ -93,7 +92,7 @@
       function immediateInit() {
         const { timeout } = props;
         timeout &&
-          useTimeout(() => {
+          useTimeoutFn(() => {
             init();
           }, timeout);
       }
@@ -101,7 +100,7 @@
       function init() {
         state.loading = true;
 
-        useTimeout(() => {
+        useTimeoutFn(() => {
           if (state.isInit) return;
           state.isInit = true;
           emit('init');

+ 3 - 2
src/components/Container/src/collapse/CollapseContainer.vue

@@ -32,7 +32,8 @@
 
   import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent';
   // hook
-  import { useTimeout } from '/@/hooks/core/useTimeout';
+  import { useTimeoutFn } from '@vueuse/core';
+
   export default defineComponent({
     components: {
       Skeleton,
@@ -89,7 +90,7 @@
 
         if (props.triggerWindowResize) {
           // 这里200毫秒是因为展开有动画,
-          useTimeout(triggerWindowResize, 200);
+          useTimeoutFn(triggerWindowResize, 200);
         }
       }
       return {

+ 1 - 3
src/components/CountTo/src/index.vue

@@ -6,15 +6,13 @@
 <script lang="ts">
   import { defineComponent, reactive, computed, watch, onMounted, unref, toRef } from 'vue';
   import { countToProps } from './props';
-  import { useRaf } from '/@/hooks/event/useRaf';
   import { isNumber } from '/@/utils/is';
+  import { requestAnimationFrame, cancelAnimationFrame } from '/@/utils/animation';
   export default defineComponent({
     name: 'CountTo',
     props: countToProps,
     emits: ['mounted', 'callback'],
     setup(props, { emit }) {
-      const { requestAnimationFrame, cancelAnimationFrame } = useRaf();
-
       const state = reactive<{
         localStartVal: number;
         printVal: number | null;

+ 2 - 2
src/components/Modal/src/Modal.tsx

@@ -1,7 +1,7 @@
 import { Modal } from 'ant-design-vue';
 import { defineComponent, watchEffect } from 'vue';
 import { basicProps } from './props';
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 import { extendSlots } from '/@/utils/helper/tsxHelper';
 
 export default defineComponent({
@@ -99,7 +99,7 @@ export default defineComponent({
       if (!props.visible) {
         return;
       }
-      useTimeout(() => {
+      useTimeoutFn(() => {
         handleDrag();
       }, 30);
     });

+ 1 - 13
src/components/Modal/src/ModalWrapper.tsx

@@ -14,8 +14,7 @@ import {
 } from 'vue';
 import { Spin } from 'ant-design-vue';
 
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
-// import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
 
 import { getSlot } from '/@/utils/helper/tsxHelper';
 import { useElResize } from '/@/hooks/event/useElResize';
@@ -126,17 +125,6 @@ export default defineComponent({
         }
         await nextTick();
         const spinEl = unref(spinRef);
-        // if (!spinEl) {
-        //   useTimeout(() => {
-        //     // retry
-        //     if (tryCount < 3) {
-        //       setModalHeight();
-        //     }
-        //     tryCount++;
-        //   }, 10);
-        //   return;
-        // }
-        // tryCount = 0;
 
         const spinContainerEl = spinEl.$el.querySelector('.ant-spin-container') as HTMLElement;
         if (!spinContainerEl) return;

+ 2 - 2
src/components/Table/src/BasicTable.vue

@@ -64,7 +64,7 @@
   import { useTableScroll } from './hooks/useTableScroll';
   import { provideTable } from './hooks/useProvinceTable';
 
-  import { useEvent } from '/@/hooks/event/useEvent';
+  import { useEventListener } from '/@/hooks/event/useEventListener';
   import { basicProps } from './props';
   import { ROW_KEY } from './const';
   import './style/index.less';
@@ -245,7 +245,7 @@
             }
             const bodyDomList = tableEl.$el.querySelectorAll('.ant-table-body') as HTMLDivElement[];
             const bodyDom = bodyDomList[0];
-            useEvent({
+            useEventListener({
               el: bodyDom,
               name: 'scroll',
               listener: () => {

+ 2 - 2
src/components/Table/src/hooks/useDataSource.ts

@@ -3,7 +3,7 @@ import type { PaginationProps } from '../types/pagination';
 
 import { watch, ref, unref, ComputedRef, computed, onMounted, Ref } from 'vue';
 
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 
 import { buildUUID } from '/@/utils/uuid';
 import { isFunction, isBoolean } from '/@/utils/is';
@@ -145,7 +145,7 @@ export function useDataSource(
   }
   onMounted(() => {
     // 转异步任务
-    useTimeout(() => {
+    useTimeoutFn(() => {
       unref(propsRef).immediate && fetch();
     }, 0);
   });

+ 1 - 12
src/components/Table/src/hooks/useTableScroll.ts

@@ -6,7 +6,7 @@ import { injectModal } from '/@/components/Modal/src/provideModal';
 import { getViewportOffset } from '/@/utils/domUtils';
 import { isBoolean } from '/@/utils/is';
 
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
+import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
 import { useProps } from './useProps';
 
 export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRef: Ref<any>) {
@@ -110,17 +110,6 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
       nextTick(() => {
         calcTableHeight();
       });
-      // const hasFixedLeft = (unref(propsRef).columns || []).some((item) => item.fixed === 'left');
-      // // TODO antv table问题情况太多,只能先用下面方式定时器hack
-      // useTimeout(() => {
-      //   calcTableHeight(() => {
-      //     // 有左侧固定列的时候才有问题
-      //     hasFixedLeft &&
-      //       useTimeout(() => {
-      //         triggerWindowResize();
-      //       }, 300);
-      //   });
-      // }, 200);
     }
   });
   const getScrollRef = computed(() => {

+ 4 - 4
src/components/Verify/src/DragVerify.tsx

@@ -1,6 +1,6 @@
 import { defineComponent, ref, computed, unref, reactive, watch, watchEffect } from 'vue';
-import { useTimeout } from '/@/hooks/core/useTimeout';
-import { useEvent } from '/@/hooks/event/useEvent';
+import { useTimeoutFn } from '@vueuse/core';
+import { useEventListener } from '/@/hooks/event/useEventListener';
 import { basicProps } from './props';
 import { getSlot } from '/@/utils/helper/tsxHelper';
 import './DragVerify.less';
@@ -91,7 +91,7 @@ export default defineComponent({
       return (e as MouseEvent).pageX || (e as TouchEvent).touches[0].pageX;
     }
 
-    useEvent({
+    useEventListener({
       el: document,
       name: 'mouseup',
       listener: () => {
@@ -201,7 +201,7 @@ export default defineComponent({
       const contentEl = unref(contentElRef);
       if (!actionEl || !barEl || !contentEl) return;
       state.toLeft = true;
-      useTimeout(() => {
+      useTimeoutFn(() => {
         state.toLeft = false;
         actionEl.style.left = '0';
         barEl.style.width = '0';

+ 2 - 2
src/components/Verify/src/ImgRotate.tsx

@@ -1,7 +1,7 @@
 import type { MoveData, DragVerifyActionType } from './types';
 
 import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue';
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 
 import BasicDragVerify from './DragVerify';
 
@@ -86,7 +86,7 @@ export default defineComponent({
       if (Math.abs(randomRotate - currentRotate) >= (diffDegree || 20)) {
         state.imgStyle = hackCss('transform', `rotateZ(${randomRotate}deg)`);
         state.toOrigin = true;
-        useTimeout(() => {
+        useTimeoutFn(() => {
           state.toOrigin = false;
           state.showTip = true;
           //  时间与动画时间保持一致

+ 2 - 2
src/components/Verify/src/VerifyModal.vue

@@ -1,7 +1,7 @@
 <script lang="tsx">
   import { defineComponent, ref, unref } from 'vue';
   import { BasicModal } from '/@/components/Modal/index';
-  import { useTimeout } from '/@/hooks/core/useTimeout';
+  import { useTimeoutFn } from '@vueuse/core';
 
   import { RotateDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
   export default defineComponent({
@@ -11,7 +11,7 @@
       const dragRef = ref<DragVerifyActionType | null>(null);
 
       function handleSuccess() {
-        useTimeout(() => {
+        useTimeoutFn(() => {
           emit('success');
           const dragEl = unref(dragRef);
           if (dragEl) {

+ 2 - 2
src/components/VirtualScroll/src/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent, computed, ref, unref, reactive, onMounted, watch, nextTick } from 'vue';
-import { useEvent } from '/@/hooks/event/useEvent';
+import { useEventListener } from '/@/hooks/event/useEventListener';
 
 import { convertToUnit } from '/@/components/util';
 import { props as basicProps } from './props';
@@ -109,7 +109,7 @@ export default defineComponent({
         if (!wrapEl) {
           return;
         }
-        useEvent({
+        useEventListener({
           el: wrapEl,
           name: 'scroll',
           listener: onScroll,

+ 0 - 56
src/hooks/core/asyncComputed.ts

@@ -1,56 +0,0 @@
-import { ref, watchEffect, Ref } from 'vue';
-
-/**
- * Handle overlapping async evaluations
- *
- * @param cancelCallback The provided callback is invoked when a re-evaluation of the computed value is triggered before the previous one finished
- */
-export type AsyncComputedOnCancel = (cancelCallback: () => void) => void;
-
-/**
- * A two-item tuple with the first item being a ref to the computed value and the second item holding a boolean ref, indicating whether the async computed value is currently (re-)evaluated
- */
-export type AsyncComputedResult<T> = [Ref<T>, Ref<boolean>];
-
-/**
- * Create an asynchronous computed dependency
- *
- * @param evaluationCallback     The promise-returning callback which generates the computed value
- * @param defaultValue           A default value, used until the first evaluation finishes
- */
-export function asyncComputed<T>(
-  evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
-  defaultValue?: T
-): AsyncComputedResult<T> {
-  let counter = 0;
-  const current = ref(defaultValue) as Ref<T>;
-  const evaluating = ref<boolean>(false);
-
-  watchEffect(async (onInvalidate: Fn) => {
-    counter++;
-    const counterAtBeginning = counter;
-    let hasFinished = false;
-
-    try {
-      // Defer initial setting of `evaluating` ref
-      // to avoid having it as a dependency
-      Promise.resolve().then(() => {
-        evaluating.value = true;
-      });
-
-      const result = await evaluationCallback((cancelCallback) => {
-        onInvalidate(() => {
-          evaluating.value = false;
-          if (!hasFinished) cancelCallback();
-        });
-      });
-
-      if (counterAtBeginning === counter) current.value = result;
-    } finally {
-      evaluating.value = false;
-      hasFinished = true;
-    }
-  });
-
-  return [current, evaluating];
-}

+ 0 - 16
src/hooks/core/useCounter.ts

@@ -1,16 +0,0 @@
-import { ref } from 'vue';
-
-export function useCounter(initialValue = 0) {
-  const count = ref(initialValue);
-
-  const inc = (delta = 1) => (count.value += delta);
-  const dec = (delta = 1) => (count.value -= delta);
-  const get = () => count.value;
-  const set = (val: number) => (count.value = val);
-  const reset = (val = initialValue) => {
-    initialValue = val;
-    return set(val);
-  };
-
-  return { count, inc, dec, get, set, reset };
-}

+ 0 - 23
src/hooks/core/useTimeout.ts

@@ -1,23 +0,0 @@
-import { isFunction } from '/@/utils/is';
-import { Ref, watch } from 'vue';
-
-import { useTimeoutRef } from '/@/hooks/core/useTimeoutRef';
-
-type TimeoutFnResult = [Fn<void>, Fn<void>, Ref<boolean>];
-
-export function useTimeout(handle: Fn<any>, wait: number): TimeoutFnResult {
-  if (!isFunction(handle)) {
-    throw new Error('handle is not Function!');
-  }
-
-  const [readyRef, clear, runAgain] = useTimeoutRef(wait);
-
-  watch(
-    readyRef,
-    (maturity) => {
-      maturity && handle();
-    },
-    { immediate: false }
-  );
-  return [clear, runAgain, readyRef];
-}

+ 0 - 24
src/hooks/core/useTimeoutRef.ts

@@ -1,24 +0,0 @@
-import { Ref, ref } from 'vue';
-import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
-export type TimeoutResult = [Ref<boolean>, Fn<void>, Fn<void>];
-export function useTimeoutRef(wait: number): TimeoutResult {
-  const readyRef = ref(false);
-
-  let timer: ReturnType<typeof setTimeout> | undefined;
-  function clear(): void {
-    readyRef.value = false;
-    timer && window.clearTimeout(timer);
-  }
-  function openTimer(): void {
-    clear();
-    timer = setTimeout(() => {
-      readyRef.value = true;
-    }, wait);
-  }
-
-  openTimer();
-
-  tryOnUnmounted(clear);
-
-  return [readyRef, clear, openTimer];
-}

+ 6 - 6
src/hooks/event/useBreakpoint.ts

@@ -1,10 +1,10 @@
-import { ref, computed, Ref, unref } from 'vue';
-import { useEvent } from './useEvent';
+import { ref, computed, ComputedRef, unref } from 'vue';
+import { useEventListener } from '/@/hooks/event/useEventListener';
 import { screenMap, sizeEnum, screenEnum } from '/@/enums/breakpointEnum';
 
-let globalScreenRef: Ref<sizeEnum | undefined>;
-let globalWidthRef: Ref<number>;
-let globalRealWidthRef: Ref<number>;
+let globalScreenRef: ComputedRef<sizeEnum | undefined>;
+let globalWidthRef: ComputedRef<number>;
+let globalRealWidthRef: ComputedRef<number>;
 
 export function useBreakpoint() {
   return {
@@ -43,7 +43,7 @@ export function createBreakpointListen(fn?: Fn) {
     realWidthRef.value = width;
   }
 
-  useEvent({
+  useEventListener({
     el: window,
     name: 'resize',
     listener: () => {

+ 0 - 10
src/hooks/event/useEventHub.ts

@@ -1,10 +0,0 @@
-import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
-import EventHub from '/@/utils/eventHub';
-const eventHub = new EventHub();
-export function useEventHub(): EventHub {
-  tryOnUnmounted(() => {
-    eventHub.clear();
-  });
-
-  return eventHub;
-}

+ 1 - 1
src/hooks/event/useEvent.ts → src/hooks/event/useEventListener.ts

@@ -15,7 +15,7 @@ export interface UseEventParams {
   isDebounce?: boolean;
   wait?: number;
 }
-export function useEvent({
+export function useEventListener({
   el = window,
   name,
   listener,

+ 0 - 48
src/hooks/event/useIntersectionObserver.ts

@@ -1,48 +0,0 @@
-import { Ref, watchEffect, ref } from 'vue';
-
-interface IntersectionObserverProps {
-  target: Ref<Element | null | undefined>;
-  root?: Ref<Element | null | undefined>;
-  onIntersect: IntersectionObserverCallback;
-  rootMargin?: string;
-  threshold?: number;
-}
-
-export function useIntersectionObserver({
-  target,
-  root,
-  onIntersect,
-  rootMargin = '0px',
-  threshold = 0.1,
-}: IntersectionObserverProps) {
-  let cleanup = () => {};
-  const observer: Ref<Nullable<IntersectionObserver>> = ref(null);
-  const stopEffect = watchEffect(() => {
-    cleanup();
-
-    observer.value = new IntersectionObserver(onIntersect, {
-      root: root ? root.value : null,
-      rootMargin,
-      threshold,
-    });
-
-    const current = target.value;
-
-    current && observer.value.observe(current);
-
-    cleanup = () => {
-      if (observer.value) {
-        observer.value.disconnect();
-        target.value && observer.value.unobserve(target.value);
-      }
-    };
-  });
-
-  return {
-    observer,
-    stop: () => {
-      cleanup();
-      stopEffect();
-    },
-  };
-}

+ 0 - 35
src/hooks/event/useNow.ts

@@ -1,35 +0,0 @@
-import { ref } from 'vue';
-import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
-
-function getTimestamp() {
-  return +Date.now();
-}
-
-export function useNow() {
-  const now = ref(getTimestamp());
-  let started = false;
-
-  const update = () => {
-    requestAnimationFrame(() => {
-      now.value = getTimestamp();
-      if (started) update();
-    });
-  };
-
-  const start = () => {
-    if (!started) {
-      started = true;
-      update();
-    }
-  };
-
-  const stop = () => {
-    started = false;
-  };
-
-  start();
-
-  tryOnUnmounted(stop);
-
-  return now;
-}

+ 0 - 95
src/hooks/event/useRaf.ts

@@ -1,95 +0,0 @@
-import { isServer } from '/@/utils/is';
-import { onUnmounted, getCurrentInstance } from 'vue';
-let lastTime = 0;
-const prefixes = 'webkit moz ms o'.split(' '); // Each browser prefix
-
-let requestAnimationFrame: any;
-let cancelAnimationFrame: any;
-
-/* eslint-disable-next-line */
-const NO_LOOP = () => {};
-
-const getWindowFrame = (name: string) => {
-  return name as any;
-};
-if (isServer) {
-  requestAnimationFrame = cancelAnimationFrame = NO_LOOP;
-} else {
-  requestAnimationFrame = window.requestAnimationFrame;
-  cancelAnimationFrame = window.cancelAnimationFrame;
-  let prefix;
-  for (let i = 0; i < prefixes.length; i++) {
-    if (requestAnimationFrame && cancelAnimationFrame) {
-      break;
-    }
-    prefix = prefixes[i];
-    requestAnimationFrame =
-      requestAnimationFrame || window[getWindowFrame(prefix + 'RequestAnimationFrame')];
-    cancelAnimationFrame =
-      cancelAnimationFrame ||
-      window[getWindowFrame(prefix + 'CancelAnimationFrame')] ||
-      window[getWindowFrame(prefix + 'CancelRequestAnimationFrame')];
-  }
-
-  // If the current browser does not support requestAnimationFrame and cancelAnimationFrame, it will fall back to setTimeout
-  if (!requestAnimationFrame || !cancelAnimationFrame) {
-    requestAnimationFrame = function (callback: Fn) {
-      const currTime = new Date().getTime();
-      const timeToCall = Math.max(0, 16 - (currTime - lastTime));
-      const id = window.setTimeout(() => {
-        /* eslint-disable-next-line */
-        callback(currTime + timeToCall);
-      }, timeToCall);
-      lastTime = currTime + timeToCall;
-      return id;
-    };
-
-    cancelAnimationFrame = function (id: number) {
-      window.clearTimeout(id);
-    };
-  }
-}
-export function useRaf() {
-  // if (getCurrentInstance()) {
-  //   onUnmounted(() => {
-  //     cancelAnimationFrame();
-  //   });
-  // }
-  return { requestAnimationFrame, cancelAnimationFrame };
-}
-
-export function useRafFn(fn: (...arg: any) => any, options: { immediate?: boolean } = {}) {
-  const { immediate = false } = options;
-  let started = false;
-  let id: ReturnType<typeof window.requestAnimationFrame>;
-
-  function loop() {
-    if (!started) return;
-    fn();
-    id = requestAnimationFrame(loop);
-  }
-
-  function start() {
-    if (!started) {
-      started = true;
-      loop();
-    }
-  }
-
-  function stop() {
-    started = false;
-  }
-
-  if (immediate) {
-    start();
-  }
-
-  if (getCurrentInstance()) {
-    onUnmounted(() => {
-      cancelAnimationFrame(id);
-      stop();
-    });
-  }
-
-  return { stop, start };
-}

+ 2 - 2
src/hooks/event/useScrollTo.ts

@@ -1,6 +1,7 @@
-import { useRaf } from '/@/hooks/event/useRaf';
 import { isFunction, isUnDef } from '/@/utils/is';
 import { ref, unref } from 'vue';
+import { requestAnimationFrame } from '/@/utils/animation';
+
 export interface ScrollToParams {
   el: HTMLElement;
   to: number;
@@ -30,7 +31,6 @@ export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams
   const increment = 20;
   let currentTime = 0;
   duration = isUnDef(duration) ? 500 : duration;
-  const { requestAnimationFrame } = useRaf();
 
   const animateScroll = function () {
     if (!unref(isActiveRef)) {

+ 0 - 20
src/hooks/event/useWindowSize.ts → src/hooks/event/useWindowSizeFn.ts

@@ -1,5 +1,4 @@
 import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
-import { ref } from 'vue';
 
 import { useDebounce } from '/@/hooks/core/useDebounce';
 
@@ -37,22 +36,3 @@ export function useWindowSizeFn<T>(fn: Fn<T>, wait = 150, options?: WindowSizeOp
   });
   return [start, stop];
 }
-
-export const useWindowSize = (wait = 150, options?: WindowSizeOptions) => {
-  const widthRef = ref(0);
-  const heightRef = ref(0);
-
-  function setSize() {
-    widthRef.value = window.innerWidth;
-    heightRef.value = window.innerHeight;
-  }
-  setSize();
-
-  const handler = () => {
-    setSize();
-  };
-
-  useWindowSizeFn(handler, wait, options);
-
-  return { widthRef: widthRef, heightRef: heightRef };
-};

+ 0 - 12
src/hooks/state/useGlobalState.ts

@@ -1,12 +0,0 @@
-import { reactive } from 'vue';
-
-export function createGlobalState<T extends object>(factory: () => T) {
-  let state: T;
-
-  return () => {
-    if (!state) {
-      state = reactive(factory()) as T;
-    }
-    return state;
-  };
-}

+ 2 - 2
src/hooks/web/useApexCharts.ts

@@ -1,4 +1,4 @@
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
 import { unref, Ref, nextTick } from 'vue';
 
@@ -9,7 +9,7 @@ export function useApexCharts(elRef: Ref<HTMLDivElement>) {
 
   function setOptions(options: any) {
     nextTick(() => {
-      useTimeout(() => {
+      useTimeoutFn(() => {
         const el = unref(elRef);
 
         if (!el || !unref(el)) return;

+ 3 - 3
src/hooks/web/useClickOutside.ts

@@ -1,17 +1,17 @@
 import { ref, Ref, unref } from 'vue';
-import { useEvent } from '/@/hooks/event/useEvent';
+import { useEventListener } from '/@/hooks/event/useEventListener';
 export function useClickOutside<T extends HTMLElement>(
   containerRef: Ref<T>,
   onClickOutside: (e: MouseEvent | TouchEvent) => void
 ) {
   const isTouchRef = ref(false);
-  useEvent({
+  useEventListener({
     el: document,
     name: 'touchend',
     listener: handler,
     options: true,
   });
-  useEvent({
+  useEventListener({
     el: document,
     name: 'click',
     listener: handler,

+ 0 - 40
src/hooks/web/useCssVar.ts

@@ -1,40 +0,0 @@
-// import { ref, Ref, isRef, watch } from '@vue/runtime-dom';
-
-// TODO 打开注释会造成热更新失效,待排查
-// export default function useCssVar(prop: string, refEl?: Ref<HTMLElement | null>) {
-//   const refVar = ref('');
-//   let el: HTMLElement = document.documentElement;
-
-//   if (isRef(refEl)) {
-//     watch(
-//       refEl,
-//       () => {
-//         if (refEl.value) {
-//           el = refEl.value as HTMLElement;
-//           refVar.value = getComputedStyle(el).getPropertyValue(prop);
-//         }
-//       },
-//       { immediate: true }
-//     );
-//   } else {
-//     refVar.value = getComputedStyle(el).getPropertyValue(prop);
-//   }
-
-//   watch(
-//     refVar,
-//     (val) => {
-//       el && el.style.setProperty(prop, val);
-//     },
-//     { immediate: true }
-//   );
-
-//   return refVar;
-// }
-
-export function getCssVar(prop: string, dom = document.documentElement) {
-  return getComputedStyle(dom).getPropertyValue(prop);
-}
-
-export function setCssVar(prop: string, val: any, dom = document.documentElement) {
-  dom.style.setProperty(prop, val);
-}

+ 5 - 5
src/hooks/web/useECharts.ts

@@ -1,10 +1,10 @@
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
 import { unref, Ref, nextTick } from 'vue';
 import type { EChartOption, ECharts } from 'echarts';
 import echarts from 'echarts';
 import { useDebounce } from '/@/hooks/core/useDebounce';
-import { useEvent } from '/@/hooks/event/useEvent';
+import { useEventListener } from '/@/hooks/event/useEventListener';
 import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
 
 export type { EChartOption, ECharts };
@@ -26,7 +26,7 @@ export function useECharts(
       return;
     }
     chartInstance = echarts.init(el, theme);
-    const { removeEvent } = useEvent({
+    const { removeEvent } = useEventListener({
       el: window,
       name: 'resize',
       listener: resizeFn,
@@ -34,7 +34,7 @@ export function useECharts(
     removeResizeFn = removeEvent;
     const { widthRef, screenEnum } = useBreakpoint();
     if (unref(widthRef) <= screenEnum.MD) {
-      useTimeout(() => {
+      useTimeoutFn(() => {
         resizeFn();
       }, 30);
     }
@@ -42,7 +42,7 @@ export function useECharts(
 
   function setOptions(options: any, clear = true) {
     nextTick(() => {
-      useTimeout(() => {
+      useTimeoutFn(() => {
         if (!chartInstance) {
           init();
 

+ 0 - 5
src/hooks/web/useLocalStorage.ts

@@ -1,5 +0,0 @@
-import { createStorage } from '/@/utils/storage';
-
-export function useLocalStorage() {
-  return createStorage(localStorage);
-}

+ 0 - 53
src/hooks/web/useNetWork.ts

@@ -1,53 +0,0 @@
-import type { Ref } from 'vue';
-
-import { ref, watch } from 'vue';
-import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
-
-import { isBoolean } from '/@/utils/is';
-
-const ON_LINE = 'online';
-const OFF_LINE = 'offline';
-export function useNetWork({
-  onLineFn,
-  offLineFn,
-}: {
-  onLineFn?: () => void;
-  offLineFn?: () => void;
-}) {
-  const onLineRef = ref(navigator.onLine);
-
-  // Disconnect time
-  const offlineAt: Ref<number | undefined> = ref(undefined);
-
-  watch(
-    () => onLineRef.value,
-    (onLine, oldValue): void => {
-      if (isBoolean(oldValue) && !oldValue && onLine) {
-        onLineFn && onLineFn();
-      } else if (isBoolean(onLine) && !onLine && oldValue) {
-        // Network to no network
-        offlineAt.value = Date.now();
-        offLineFn && offLineFn();
-      }
-    },
-    {
-      immediate: false,
-    }
-  );
-
-  const handler = (e: Event) => {
-    const { type } = e;
-    onLineRef.value = type === ON_LINE;
-  };
-  tryOnMounted(() => {
-    window.addEventListener(ON_LINE, handler);
-    window.addEventListener(OFF_LINE, handler);
-  });
-  tryOnUnmounted(() => {
-    window.removeEventListener(ON_LINE, handler);
-    window.removeEventListener(OFF_LINE, handler);
-  });
-  return {
-    onLineRef,
-  };
-}

+ 0 - 5
src/hooks/web/useSessionStorage.ts

@@ -1,5 +0,0 @@
-import { createStorage } from '/@/utils/storage';
-
-export function useSessionStorage() {
-  return createStorage(sessionStorage);
-}

+ 2 - 2
src/hooks/web/useTabs.ts

@@ -1,4 +1,4 @@
-import { useTimeout } from '/@/hooks/core/useTimeout';
+import { useTimeoutFn } from '@vueuse/core';
 import { PageEnum } from '/@/enums/pageEnum';
 import { TabItem, tabStore } from '/@/store/modules/tab';
 import { appStore } from '/@/store/modules/app';
@@ -98,7 +98,7 @@ export function useTabs() {
       const to = getTo(path);
 
       if (!to) return;
-      useTimeout(() => {
+      useTimeoutFn(() => {
         tabStore.addTabByPathAction();
       }, 0);
       const { replace, query = {}, params = {} } = opt || {};

+ 0 - 32
src/hooks/web/useTitle.ts

@@ -1,32 +0,0 @@
-import type { Ref } from 'vue';
-
-import { ref, watch } from 'vue';
-import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
-import { isString } from '/@/utils/is';
-
-export function useTitle(overrideTitle: string | null = null): Ref<string | null> {
-  const title = ref<string | null>(isString(overrideTitle) ? overrideTitle : document.title);
-  const observer = new MutationObserver((m) => {
-    title.value = m[0].target.textContent;
-  });
-
-  watch(
-    title,
-    (t, o) => {
-      if (isString(t) && t !== o) {
-        document.title = t;
-      }
-    },
-    {
-      immediate: true,
-      flush: 'sync',
-    }
-  );
-
-  const titleElement = document.querySelector('title')!;
-  observer.observe(titleElement, { childList: true });
-  tryOnUnmounted(() => {
-    observer.disconnect();
-  });
-  return title;
-}

+ 0 - 20
src/hooks/web/useVisibilityState.ts

@@ -1,20 +0,0 @@
-import { ref, onUnmounted, computed } from '@vue/runtime-dom';
-import { isDef } from '/@/utils/is';
-
-export default function useVisibilityState() {
-  const refVisibility = ref(true);
-
-  if (isDef(document) && isDef(document.visibilityState)) {
-    const setVisibility = () => {
-      refVisibility.value = document.visibilityState === 'visible';
-    };
-
-    document.addEventListener('visibilitychange', setVisibility, false);
-
-    onUnmounted(() => {
-      document.removeEventListener('visibilitychange', setVisibility);
-    });
-  }
-
-  return computed(() => refVisibility.value);
-}

+ 1 - 1
src/layouts/default/header/LayoutHeader.tsx

@@ -19,7 +19,7 @@ import {
 
 import { useFullscreen } from '/@/hooks/web/useFullScreen';
 import { useTabs } from '/@/hooks/web/useTabs';
-import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
+import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
 import { useRouter } from 'vue-router';
 import { useModal } from '/@/components/Modal';
 

+ 2 - 2
src/layouts/logo/index.vue

@@ -8,7 +8,7 @@
   import { computed, defineComponent, PropType, ref, watch } from 'vue';
   // hooks
   import { useSetting } from '/@/hooks/core/useSetting';
-  import { useTimeout } from '/@/hooks/core/useTimeout';
+  import { useTimeoutFn } from '@vueuse/core';
   import { useGo } from '/@/hooks/web/usePage';
 
   import { PageEnum } from '/@/enums/pageEnum';
@@ -41,7 +41,7 @@
         () => props.showTitle,
         (show: boolean) => {
           if (show) {
-            useTimeout(() => {
+            useTimeoutFn(() => {
               showRef.value = show;
             }, 280);
           } else {

+ 0 - 3
src/settings/projectSetting.ts

@@ -128,9 +128,6 @@ const setting: ProjectConfig = {
   // 是否开启登录安全校验
   openLoginVerify: true,
 
-  // 是否监听网络变化
-  listenNetWork: false,
-
   // 是否开启页面切换loading
   openPageLoading: true,
 

+ 4 - 1
src/setup/theme/index.ts

@@ -1,4 +1,3 @@
-import { setCssVar } from '/@/hooks/web/useCssVar';
 import { isHexColor, colorIsDark, lighten, darken } from '/@/utils/color';
 import { appStore } from '/@/store/modules/app';
 import { MenuThemeEnum } from '/@/enums/menuEnum';
@@ -12,6 +11,10 @@ const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
 const SIDER_LIGHTEN_1_BG_COLOR = '--sider-dark-lighten-1-bg-color';
 const SIDER_LIGHTEN_2_BG_COLOR = '--sider-dark-lighten-2-bg-color';
 
+export function setCssVar(prop: string, val: any, dom = document.documentElement) {
+  dom.style.setProperty(prop, val);
+}
+
 function toggleClass(flag: boolean, clsName: string) {
   const body = document.body;
   let { className } = body;

+ 0 - 2
src/types/config.d.ts

@@ -101,8 +101,6 @@ export interface ProjectConfig {
   routerTransition: RouterTransitionEnum;
   // 是否开启登录安全校验
   openLoginVerify: boolean;
-  // 是否监听网络变化
-  listenNetWork: boolean;
   // 是否开启页面切换loading
   openPageLoading: boolean;
   // 是否开启回到顶部

+ 0 - 30
src/useApp.ts

@@ -17,11 +17,6 @@ import {
 } from '/@/setup/theme';
 
 import { appStore } from '/@/store/modules/app';
-import { useNetWork } from '/@/hooks/web/useNetWork';
-import { useRouter } from 'vue-router';
-import { PageEnum } from '/@/enums/pageEnum';
-import { useTimeout } from '/@/hooks/core/useTimeout';
-import { ExceptionEnum } from '/@/enums/exceptionEnum';
 
 let app: App;
 export function setApp(_app: App): void {
@@ -84,28 +79,3 @@ export function useConfigProvider() {
     transformCellText,
   };
 }
-
-// Initialize network monitoring
-export function useListenerNetWork() {
-  const { listenNetWork } = appStore.getProjectConfig;
-  if (!listenNetWork) return;
-  const { replace } = useRouter();
-  // Check network status
-  useNetWork({
-    onLineFn: () => {
-      replace(PageEnum.BASE_HOME).then(() => {
-        useTimeout(() => {
-          appStore.commitPageLoadingState(false);
-        }, 200);
-      });
-    },
-    offLineFn: () => {
-      replace({
-        path: PageEnum.ERROR_PAGE,
-        query: {
-          status: String(ExceptionEnum.NET_WORK_ERROR),
-        },
-      });
-    },
-  });
-}

+ 51 - 0
src/utils/animation.ts

@@ -0,0 +1,51 @@
+import { isServer } from '/@/utils/is';
+let lastTime = 0;
+const prefixes = 'webkit moz ms o'.split(' ');
+
+let requestAnimationFrame: typeof window.requestAnimationFrame;
+let cancelAnimationFrame: typeof window.cancelAnimationFrame;
+(() => {
+  const NO_LOOP: any = () => {};
+  const getWindowFrame = (name: string) => {
+    return name as any;
+  };
+  if (isServer) {
+    requestAnimationFrame = cancelAnimationFrame = NO_LOOP;
+  } else {
+    requestAnimationFrame = window.requestAnimationFrame;
+    cancelAnimationFrame = window.cancelAnimationFrame;
+    let prefix;
+    for (let i = 0; i < prefixes.length; i++) {
+      if (requestAnimationFrame && cancelAnimationFrame) {
+        break;
+      }
+      prefix = prefixes[i];
+      requestAnimationFrame =
+        requestAnimationFrame || window[getWindowFrame(prefix + 'RequestAnimationFrame')];
+      cancelAnimationFrame =
+        cancelAnimationFrame ||
+        window[getWindowFrame(prefix + 'CancelAnimationFrame')] ||
+        window[getWindowFrame(prefix + 'CancelRequestAnimationFrame')];
+    }
+
+    // If the current browser does not support requestAnimationFrame and cancelAnimationFrame, it will fall back to setTimeout
+    if (!requestAnimationFrame || !cancelAnimationFrame) {
+      requestAnimationFrame = function (callback: Fn) {
+        const currTime = new Date().getTime();
+        const timeToCall = Math.max(0, 16 - (currTime - lastTime));
+        const id = window.setTimeout(() => {
+          /* eslint-disable-next-line */
+          callback(currTime + timeToCall);
+        }, timeToCall);
+        lastTime = currTime + timeToCall;
+        return id;
+      };
+
+      cancelAnimationFrame = function (id: number) {
+        window.clearTimeout(id);
+      };
+    }
+  }
+})();
+
+export { requestAnimationFrame, cancelAnimationFrame };

+ 1 - 1
src/views/sys/iframe/index.vue

@@ -10,7 +10,7 @@
   import { Spin } from 'ant-design-vue';
 
   import { getViewportOffset } from '/@/utils/domUtils';
-  import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
+  import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
 
   export default defineComponent({
     name: 'IFrame',

+ 20 - 0
yarn.lock

@@ -1725,6 +1725,21 @@
     vscode-languageserver-textdocument "^1.0.1"
     vscode-uri "^2.1.2"
 
+"@vueuse/core@^4.0.0-beta.40":
+  version "4.0.0-beta.40"
+  resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-beta.40.tgz#7efdc15c1b994647dff7ae65c0ca573d96ce9b28"
+  integrity sha512-FOTOUrXAAp0NOmy8hMlP1HpUhnB8LeRJZDOEUl/A9gKMDwWvPTEvxKsDAIzSa4s7I0MapVzfeP3soNCNfl9+vQ==
+  dependencies:
+    "@vueuse/shared" "4.0.0-beta.40"
+    vue-demi latest
+
+"@vueuse/shared@4.0.0-beta.40":
+  version "4.0.0-beta.40"
+  resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-beta.40.tgz#76e9b52228159e7ec88df2c8f4eea8fce1a42ec3"
+  integrity sha512-Ay71viUTXs0XX2hQ04kEExhpsCrw3KankBMP7euorsPjuQmIZjUA4NNOb45UAudg+uF5HXLpgWLvwb4cMOLHnQ==
+  dependencies:
+    vue-demi latest
+
 JSONStream@^1.0.4:
   version "1.3.5"
   resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
@@ -8233,6 +8248,11 @@ vscode-uri@^2.1.2:
   resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
   integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
 
+vue-demi@latest:
+  version "0.4.3"
+  resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.4.3.tgz#6aaa9b52f02c32b4f9d4d11f02a1ae71031453c3"
+  integrity sha512-1DzLcZgHC9ZyFEYR4qZ83TdS1u9DglG8XVesBXqtbbmqFuO7sb8KG36kMfZCszieAweRDwAAVSAzjmEMG0+WwA==
+
 vue-eslint-parser@^7.1.1:
   version "7.1.1"
   resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3"