Переглянути джерело

perf(route): refactor guard

vben 4 роки тому
батько
коміт
3b126e011c

+ 5 - 0
src/components/Modal/src/BasicModal.vue

@@ -16,6 +16,7 @@
     <template #footer v-if="!$slots.footer">
       <ModalFooter v-bind="getProps" @ok="handleOk" @cancel="handleCancel" />
     </template>
+
     <ModalWrapper
       :useWrapper="getProps.useWrapper"
       :footerOffset="wrapperFooterOffset"
@@ -30,6 +31,10 @@
     >
       <slot />
     </ModalWrapper>
+
+    <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
+      <slot :name="item" v-bind="data" />
+    </template>
   </Modal>
 </template>
 <script lang="ts">

+ 8 - 4
src/components/Modal/src/components/ModalWrapper.vue

@@ -48,6 +48,7 @@
       const wrapperRef = ref<ComponentRef>(null);
       const spinRef = ref<ElRef>(null);
       const realHeightRef = ref(0);
+      const minRealHeightRef = ref(0);
 
       let stopElResizeFn: Fn = () => {};
 
@@ -82,10 +83,13 @@
 
       watch(
         () => props.fullScreen,
-        () => {
-          setTimeout(() => {
-            setModalHeight();
-          }, 0);
+        (v) => {
+          setModalHeight();
+          if (!v) {
+            realHeightRef.value = minRealHeightRef.value;
+          } else {
+            minRealHeightRef.value = realHeightRef.value;
+          }
         }
       );
 

+ 15 - 15
src/components/Modal/src/hooks/useModalFullScreen.ts

@@ -7,7 +7,7 @@ export interface UseFullScreenContext {
 }
 
 export function useFullScreen(context: UseFullScreenContext) {
-  const formerHeightRef = ref(0);
+  // const formerHeightRef = ref(0);
   const fullScreenRef = ref(false);
 
   const getWrapClassName = computed(() => {
@@ -20,25 +20,25 @@ export function useFullScreen(context: UseFullScreenContext) {
     e && e.stopPropagation();
     fullScreenRef.value = !unref(fullScreenRef);
 
-    const modalWrapper = unref(context.modalWrapperRef);
+    // const modalWrapper = unref(context.modalWrapperRef);
 
-    if (!modalWrapper) return;
+    // if (!modalWrapper) return;
 
-    const wrapperEl = modalWrapper.$el as HTMLElement;
-    if (!wrapperEl) return;
-    const modalWrapSpinEl = wrapperEl.querySelector('.ant-spin-nested-loading') as HTMLElement;
+    // const wrapperEl = modalWrapper.$el as HTMLElement;
+    // if (!wrapperEl) return;
+    // const modalWrapSpinEl = wrapperEl.querySelector('.ant-spin-nested-loading') as HTMLElement;
 
-    if (!modalWrapSpinEl) return;
+    // if (!modalWrapSpinEl) return;
 
-    if (!unref(formerHeightRef) && unref(fullScreenRef)) {
-      formerHeightRef.value = modalWrapSpinEl.offsetHeight;
-    }
+    // if (!unref(formerHeightRef) && unref(fullScreenRef)) {
+    //   formerHeightRef.value = modalWrapSpinEl.offsetHeight;
+    // }
 
-    if (unref(fullScreenRef)) {
-      modalWrapSpinEl.style.height = `${window.innerHeight - unref(context.extHeightRef)}px`;
-    } else {
-      modalWrapSpinEl.style.height = `${unref(formerHeightRef)}px`;
-    }
+    // if (unref(fullScreenRef)) {
+    //   modalWrapSpinEl.style.height = `${window.innerHeight - unref(context.extHeightRef)}px`;
+    // } else {
+    //   modalWrapSpinEl.style.height = `${unref(formerHeightRef)}px`;
+    // }
   }
   return { getWrapClassName, handleFullScreen, fullScreenRef };
 }

+ 16 - 0
src/router/guard/httpGuard.ts

@@ -0,0 +1,16 @@
+import type { Router } from 'vue-router';
+import { useProjectSetting } from '/@/hooks/setting';
+import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
+
+export function createHttpGuard(router: Router) {
+  const { removeAllHttpPending } = useProjectSetting();
+  let axiosCanceler: Nullable<AxiosCanceler>;
+  if (removeAllHttpPending) {
+    axiosCanceler = new AxiosCanceler();
+  }
+  router.beforeEach(async () => {
+    // Switching the route will delete the previous request
+    removeAllHttpPending && axiosCanceler?.removeAllPending();
+    return true;
+  });
+}

+ 11 - 55
src/router/guard/index.ts

@@ -1,64 +1,20 @@
-import { RouteLocationNormalized, Router } from 'vue-router';
-
-import { Modal, notification } from 'ant-design-vue';
+import { Router } from 'vue-router';
 
 import { createProgressGuard } from './progressGuard';
 import { createPermissionGuard } from './permissionGuard';
 import { createPageLoadingGuard } from './pageLoadingGuard';
-
-import { useGlobSetting, useProjectSetting } from '/@/hooks/setting';
-
-import { setTitle } from '/@/utils/browser';
-import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
-
-import { useI18n } from '/@/hooks/web/useI18n';
-import { REDIRECT_NAME } from '/@/router/constant';
-import { setLastChangeTab } from '/@/logics/mitt/tabChange';
-
-const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting();
-const globSetting = useGlobSetting();
-
-const body = document.body;
-
-const isHash = (href: string) => {
-  return /^#/.test(href);
-};
+import { createTitleGuard } from './titleGuard';
+import { createMessageGuard } from './messageGuard';
+import { createScrollGuard } from './scrollGuard';
+import { createHttpGuard } from './httpGuard';
+import { createPageGuard } from './pageGuard';
 
 export function createGuard(router: Router) {
-  let axiosCanceler: Nullable<AxiosCanceler>;
-  if (removeAllHttpPending) {
-    axiosCanceler = new AxiosCanceler();
-  }
-  const loadedPageMap = new Map<string, boolean>();
-
-  router.beforeEach(async (to) => {
-    to.meta.loaded = !!loadedPageMap.get(to.path);
-    // Notify routing changes
-    setLastChangeTab(to);
-    try {
-      if (closeMessageOnSwitch) {
-        Modal.destroyAll();
-        notification.destroy();
-      }
-      // Switching the route will delete the previous request
-      removeAllHttpPending && axiosCanceler!.removeAllPending();
-    } catch (error) {
-      console.warn('basic guard error:' + error);
-    }
-    return true;
-  });
-
-  router.afterEach((to) => {
-    // scroll top
-    isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
-
-    loadedPageMap.set(to.path, true);
-
-    const { t } = useI18n();
-
-    // change html title
-    to.name !== REDIRECT_NAME && setTitle(t(to.meta.title), globSetting.title);
-  });
+  createPageGuard(router);
+  createHttpGuard(router);
+  createScrollGuard(router);
+  createMessageGuard(router);
+  createTitleGuard(router);
   createPageLoadingGuard(router);
   createProgressGuard(router);
   createPermissionGuard(router);

+ 21 - 0
src/router/guard/messageGuard.ts

@@ -0,0 +1,21 @@
+import type { Router } from 'vue-router';
+import { useProjectSetting } from '/@/hooks/setting';
+import { Modal, notification } from 'ant-design-vue';
+
+import { warn } from '/@/utils/log';
+
+export function createMessageGuard(router: Router) {
+  const { closeMessageOnSwitch } = useProjectSetting();
+
+  router.beforeEach(async () => {
+    try {
+      if (closeMessageOnSwitch) {
+        Modal.destroyAll();
+        notification.destroy();
+      }
+    } catch (error) {
+      warn('message guard error:' + error);
+    }
+    return true;
+  });
+}

+ 18 - 0
src/router/guard/pageGuard.ts

@@ -0,0 +1,18 @@
+import type { Router } from 'vue-router';
+import { setLastChangeTab } from '/@/logics/mitt/tabChange';
+
+export function createPageGuard(router: Router) {
+  const loadedPageMap = new Map<string, boolean>();
+
+  router.beforeEach(async (to) => {
+    to.meta.loaded = !!loadedPageMap.get(to.path);
+    // Notify routing changes
+    setLastChangeTab(to);
+
+    return true;
+  });
+
+  router.afterEach((to) => {
+    loadedPageMap.set(to.path, true);
+  });
+}

+ 15 - 0
src/router/guard/scrollGuard.ts

@@ -0,0 +1,15 @@
+import type { RouteLocationNormalized, Router } from 'vue-router';
+
+const isHash = (href: string) => {
+  return /^#/.test(href);
+};
+
+export function createScrollGuard(router: Router) {
+  const body = document.body;
+
+  router.afterEach(async (to) => {
+    // scroll top
+    isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
+    return true;
+  });
+}

+ 18 - 0
src/router/guard/titleGuard.ts

@@ -0,0 +1,18 @@
+import type { Router } from 'vue-router';
+
+import { useGlobSetting } from '/@/hooks/setting';
+
+import { setTitle } from '/@/utils/browser';
+import { useI18n } from '/@/hooks/web/useI18n';
+
+import { REDIRECT_NAME } from '/@/router/constant';
+
+const globSetting = useGlobSetting();
+
+export function createTitleGuard(router: Router) {
+  router.afterEach(async (to) => {
+    const { t } = useI18n();
+    to.name !== REDIRECT_NAME && setTitle(t(to.meta.title), globSetting.title);
+    return true;
+  });
+}

+ 0 - 3
src/views/demo/comp/modal/Modal1.vue

@@ -8,8 +8,5 @@
   import { BasicModal } from '/@/components/Modal';
   export default defineComponent({
     components: { BasicModal },
-    setup() {
-      return {};
-    },
   });
 </script>