Browse Source

perf(router): reduce the number of guard files

vben 3 years ago
parent
commit
327d71b8fb

+ 2 - 1
.vscode/settings.json

@@ -129,6 +129,7 @@
     "qrcode",
     "sider",
     "pinia",
-    "sider"
+    "sider",
+    "nprogress"
   ]
 }

+ 1 - 1
package.json

@@ -50,7 +50,7 @@
     "mockjs": "^1.1.0",
     "nprogress": "^0.2.0",
     "path-to-regexp": "^6.2.0",
-    "pinia": "2.0.0-beta.3",
+    "pinia": "^2.0.0-beta.3",
     "print-js": "^1.6.0",
     "qrcode": "^1.4.4",
     "sortablejs": "^1.13.0",

+ 0 - 1
src/App.vue

@@ -10,7 +10,6 @@
   import { defineComponent } from 'vue';
   import { ConfigProvider } from 'ant-design-vue';
   import { AppProvider } from '/@/components/Application';
-
   import { useTitle } from '/@/hooks/web/useTitle';
   import { useLocale } from '/@/locales/useLocale';
 

+ 1 - 1
src/components/Drawer/src/BasicDrawer.vue

@@ -137,7 +137,7 @@
       watch(
         () => props.visible,
         (newVal, oldVal) => {
-          if (newVal != oldVal) visibleRef.value = newVal;
+          if (newVal !== oldVal) visibleRef.value = newVal;
         },
         { deep: true }
       );

+ 0 - 7
src/components/Menu/src/BasicMenu.vue

@@ -19,25 +19,18 @@
 </template>
 <script lang="ts">
   import type { MenuState } from './types';
-
   import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
   import { Menu } from 'ant-design-vue';
   import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
-
   import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
-
   import { useOpenKeys } from './useOpenKeys';
   import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
-
   import { isFunction } from '/@/utils/is';
-
   import { basicProps } from './props';
   import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
   import { REDIRECT_NAME } from '/@/router/constant';
   import { useDesign } from '/@/hooks/web/useDesign';
-
   import { getCurrentParentPath } from '/@/router/menus';
-
   import { listenerRouteChange } from '/@/logics/mitt/routeChange';
   import { getAllParentPath } from '/@/router/helper/menuHelper';
 

+ 2 - 1
src/components/registerGlobComp.ts

@@ -5,6 +5,7 @@ import {
   // Need
   Button as AntButton,
   Input,
+  Layout,
 } from 'ant-design-vue';
 
 const compList = [AntButton.Group];
@@ -14,5 +15,5 @@ export function registerGlobComp(app: App) {
     app.component(comp.name || comp.displayName, comp);
   });
 
-  app.use(Input).use(Button);
+  app.use(Input).use(Button).use(Layout);
 }

+ 0 - 3
src/layouts/default/menu/useLayoutMenu.ts

@@ -1,13 +1,10 @@
 import type { Menu } from '/@/router/types';
 import type { Ref } from 'vue';
-
 import { watch, unref, ref, computed } from 'vue';
 import { useRouter } from 'vue-router';
-
 import { MenuSplitTyeEnum } from '/@/enums/menuEnum';
 import { useThrottleFn } from '@vueuse/core';
 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
-
 import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
 import { usePermissionStore } from '/@/store/modules/permission';
 import { useAppInject } from '/@/hooks/web/useAppInject';

+ 0 - 5
src/layouts/default/sider/MixSider.vue

@@ -81,24 +81,19 @@
   import type { Menu } from '/@/router/types';
   import type { CSSProperties } from 'vue';
   import type { RouteLocationNormalized } from 'vue-router';
-
   import { defineComponent, onMounted, ref, computed, unref } from 'vue';
-
   import { ScrollContainer } from '/@/components/Container';
   import { SimpleMenuTag } from '/@/components/SimpleMenu';
   import { Icon } from '/@/components/Icon';
   import { AppLogo } from '/@/components/Application';
   import Trigger from '../trigger/HeaderTrigger.vue';
-
   import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
   import { useDragLine } from './useLayoutSider';
   import { useGlobSetting } from '/@/hooks/setting';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useGo } from '/@/hooks/web/usePage';
-
   import { SIDE_BAR_SHOW_TIT_MINI_WIDTH, SIDE_BAR_MINI_WIDTH } from '/@/enums/appEnum';
-
   import clickOutside from '/@/directives/clickOutside';
   import { getShallowMenus, getChildrenMenus, getCurrentParentPath } from '/@/router/menus';
   import { listenerRouteChange } from '/@/logics/mitt/routeChange';

+ 1 - 3
src/main.ts

@@ -1,9 +1,7 @@
 import '/@/design/index.less';
 import '/@/design/tailwind.css';
-
 // Register icon sprite
 import 'virtual:svg-icons-register';
-
 import App from './App.vue';
 import { createApp } from 'vue';
 import { initAppConfigStore } from '/@/logics/initAppConfig';
@@ -42,7 +40,7 @@ async function bootstrap() {
   setupRouter(app);
 
   // router-guard
-  setupRouterGuard();
+  setupRouterGuard(router);
 
   // Register global directive
   setupGlobDirectives(app);

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

@@ -1,20 +0,0 @@
-import type { Router } from 'vue-router';
-import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
-import projectSetting from '/@/settings/projectSetting';
-
-/**
- * The interface used to close the current page to complete the request when the route is switched
- * @param router
- */
-export function createHttpGuard(router: Router) {
-  const { removeAllHttpPending } = projectSetting;
-  let axiosCanceler: Nullable<AxiosCanceler>;
-  if (removeAllHttpPending) {
-    axiosCanceler = new AxiosCanceler();
-  }
-  router.beforeEach(async () => {
-    // Switching the route will delete the previous request
-    axiosCanceler?.removeAllPending();
-    return true;
-  });
-}

+ 133 - 9
src/router/guard/index.ts

@@ -1,15 +1,19 @@
-import { router } from '/@/router';
-
-import { createProgressGuard } from './progressGuard';
+import type { Router, RouteLocationNormalized } from 'vue-router';
+import { useAppStoreWidthOut } from '/@/store/modules/app';
+import { useUserStoreWidthOut } from '/@/store/modules/user';
+import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
+import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
+import { Modal, notification } from 'ant-design-vue';
+import { warn } from '/@/utils/log';
+import { unref } from 'vue';
+import { setRouteChange } from '/@/logics/mitt/routeChange';
 import { createPermissionGuard } from './permissionGuard';
-import { createPageLoadingGuard } from './pageLoadingGuard';
-import { createMessageGuard } from './messageGuard';
-import { createScrollGuard } from './scrollGuard';
-import { createHttpGuard } from './httpGuard';
-import { createPageGuard } from './pageGuard';
 import { createStateGuard } from './stateGuard';
+import nProgress from 'nprogress';
+import projectSetting from '/@/settings/projectSetting';
 
-export function setupRouterGuard() {
+// Don't change the order of creation
+export function setupRouterGuard(router: Router) {
   createPageGuard(router);
   createPageLoadingGuard(router);
   createHttpGuard(router);
@@ -19,3 +23,123 @@ export function setupRouterGuard() {
   createPermissionGuard(router);
   createStateGuard(router);
 }
+
+/**
+ * Hooks for handling page state
+ */
+function createPageGuard(router: Router) {
+  const loadedPageMap = new Map<string, boolean>();
+
+  router.beforeEach(async (to) => {
+    // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
+    to.meta.loaded = !!loadedPageMap.get(to.path);
+    // Notify routing changes
+    setRouteChange(to);
+
+    return true;
+  });
+
+  router.afterEach((to) => {
+    loadedPageMap.set(to.path, true);
+  });
+}
+
+// Used to handle page loading status
+function createPageLoadingGuard(router: Router) {
+  const userStore = useUserStoreWidthOut();
+  const appStore = useAppStoreWidthOut();
+  const { getOpenPageLoading } = useTransitionSetting();
+  router.beforeEach(async (to) => {
+    if (!userStore.getToken) {
+      return true;
+    }
+    if (to.meta.loaded) {
+      return true;
+    }
+
+    if (unref(getOpenPageLoading)) {
+      appStore.setPageLoadingAction(true);
+      return true;
+    }
+
+    return true;
+  });
+  router.afterEach(async () => {
+    if (unref(getOpenPageLoading)) {
+      // TODO Looking for a better way
+      // The timer simulates the loading time to prevent flashing too fast,
+      setTimeout(() => {
+        appStore.setPageLoading(false);
+      }, 220);
+    }
+    return true;
+  });
+}
+
+/**
+ * The interface used to close the current page to complete the request when the route is switched
+ * @param router
+ */
+function createHttpGuard(router: Router) {
+  const { removeAllHttpPending } = projectSetting;
+  let axiosCanceler: Nullable<AxiosCanceler>;
+  if (removeAllHttpPending) {
+    axiosCanceler = new AxiosCanceler();
+  }
+  router.beforeEach(async () => {
+    // Switching the route will delete the previous request
+    axiosCanceler?.removeAllPending();
+    return true;
+  });
+}
+
+// Routing switch back to the top
+function createScrollGuard(router: Router) {
+  const isHash = (href: string) => {
+    return /^#/.test(href);
+  };
+
+  const body = document.body;
+
+  router.afterEach(async (to) => {
+    // scroll top
+    isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
+    return true;
+  });
+}
+
+/**
+ * Used to close the message instance when the route is switched
+ * @param router
+ */
+export function createMessageGuard(router: Router) {
+  const { closeMessageOnSwitch } = projectSetting;
+
+  router.beforeEach(async () => {
+    try {
+      if (closeMessageOnSwitch) {
+        Modal.destroyAll();
+        notification.destroy();
+      }
+    } catch (error) {
+      warn('message guard error:' + error);
+    }
+    return true;
+  });
+}
+
+export function createProgressGuard(router: Router) {
+  const { getOpenNProgress } = useTransitionSetting();
+  router.beforeEach(async (to) => {
+    if (to.meta.loaded) {
+      return true;
+    }
+    unref(getOpenNProgress) && nProgress.start();
+    return true;
+  });
+
+  router.afterEach(async () => {
+    unref(getOpenNProgress) && nProgress.done();
+    return true;
+  });
+}

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

@@ -1,24 +0,0 @@
-import type { Router } from 'vue-router';
-import { Modal, notification } from 'ant-design-vue';
-import projectSetting from '/@/settings/projectSetting';
-import { warn } from '/@/utils/log';
-
-/**
- * Used to close the message instance when the route is switched
- * @param router
- */
-export function createMessageGuard(router: Router) {
-  const { closeMessageOnSwitch } = projectSetting;
-
-  router.beforeEach(async () => {
-    try {
-      if (closeMessageOnSwitch) {
-        Modal.destroyAll();
-        notification.destroy();
-      }
-    } catch (error) {
-      warn('message guard error:' + error);
-    }
-    return true;
-  });
-}

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

@@ -1,18 +0,0 @@
-import type { Router } from 'vue-router';
-import { setRouteChange } from '/@/logics/mitt/routeChange';
-
-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
-    setRouteChange(to);
-
-    return true;
-  });
-
-  router.afterEach((to) => {
-    loadedPageMap.set(to.path, true);
-  });
-}

+ 0 - 34
src/router/guard/pageLoadingGuard.ts

@@ -1,34 +0,0 @@
-import type { Router } from 'vue-router';
-import { useAppStoreWidthOut } from '/@/store/modules/app';
-import { useUserStoreWidthOut } from '/@/store/modules/user';
-import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
-import { unref } from 'vue';
-
-export function createPageLoadingGuard(router: Router) {
-  const userStore = useUserStoreWidthOut();
-  const appStore = useAppStoreWidthOut();
-  const { getOpenPageLoading } = useTransitionSetting();
-  router.beforeEach(async (to) => {
-    if (!userStore.getToken) {
-      return true;
-    }
-    if (to.meta.loaded) {
-      return true;
-    }
-
-    if (unref(getOpenPageLoading)) {
-      appStore.setPageLoadingAction(true);
-      return true;
-    }
-
-    return true;
-  });
-  router.afterEach(async () => {
-    if (unref(getOpenPageLoading)) {
-      setTimeout(() => {
-        appStore.setPageLoading(false);
-      }, 220);
-    }
-    return true;
-  });
-}

+ 4 - 4
src/router/guard/permissionGuard.ts

@@ -32,13 +32,11 @@ export function createPermissionGuard(router: Router) {
     // token does not exist
     if (!token) {
       // You can access without permission. You need to set the routing meta.ignoreAuth to true
-      if (
-        to.meta.ignoreAuth
-        // || to.name === FULL_PAGE_NOT_FOUND_ROUTE.name
-      ) {
+      if (to.meta.ignoreAuth) {
         next();
         return;
       }
+
       // redirect login page
       const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
         path: LOGIN_PATH,
@@ -53,10 +51,12 @@ export function createPermissionGuard(router: Router) {
       next(redirectData);
       return;
     }
+
     if (permissionStore.getIsDynamicAddedRoute) {
       next();
       return;
     }
+
     const routes = await permissionStore.buildRoutesAction();
 
     routes.forEach((route) => {

+ 0 - 22
src/router/guard/progressGuard.ts

@@ -1,22 +0,0 @@
-import type { Router } from 'vue-router';
-
-import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
-
-import nProgress from 'nprogress';
-
-import { unref } from 'vue';
-
-export function createProgressGuard(router: Router) {
-  const { getOpenNProgress } = useTransitionSetting();
-  router.beforeEach(async (to) => {
-    if (to.meta.loaded) return true;
-    unref(getOpenNProgress) && nProgress.start();
-    return true;
-  });
-
-  router.afterEach(async () => {
-    // if (to.meta.loaded) return true;
-    unref(getOpenNProgress) && nProgress.done();
-    return true;
-  });
-}

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

@@ -1,15 +0,0 @@
-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;
-  });
-}

+ 6 - 6
src/router/helper/routeHelper.ts

@@ -9,7 +9,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
 export type LayoutMapKey = 'LAYOUT';
 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
 
-const LayoutMap = new Map<String, () => Promise<typeof import('*.vue')>>();
+const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
 
 LayoutMap.set('LAYOUT', LAYOUT);
 LayoutMap.set('IFRAME', IFRAME);
@@ -27,7 +27,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
     const { component, name } = item;
     const { children } = item;
     if (component) {
-      const layoutFound = LayoutMap.get(component);
+      const layoutFound = LayoutMap.get(component as string);
       if (layoutFound) {
         item.component = layoutFound;
       } else {
@@ -66,10 +66,10 @@ function dynamicImport(
 // Turn background objects into routing objects
 export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
   routeList.forEach((route) => {
-    if (route.component) {
-      if ((route.component as string).toUpperCase() === 'LAYOUT') {
-        //route.component = LayoutMap.get(route.component as LayoutMapKey);
-        route.component = LayoutMap.get((route.component as string).toUpperCase() as LayoutMapKey);
+    const component = route.component as string;
+    if (component) {
+      if (component.toUpperCase() === 'LAYOUT') {
+        route.component = LayoutMap.get(component.toUpperCase());
       } else {
         route.children = [cloneDeep(route)];
         route.component = LAYOUT;

+ 1 - 0
src/store/index.ts

@@ -1,5 +1,6 @@
 import type { App } from 'vue';
 import { createPinia } from 'pinia';
+
 const store = createPinia();
 
 export function setupStore(app: App<Element>) {

+ 2 - 1
src/utils/mitt.ts

@@ -1,5 +1,6 @@
 /**
- * https://github.com/developit/mitt
+ * copy to https://github.com/developit/mitt
+ * Expand clear method
  */
 
 export type EventType = string | symbol;

+ 1 - 1
yarn.lock

@@ -9278,7 +9278,7 @@ pify@^4.0.1:
   resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
   integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
 
-pinia@2.0.0-beta.3:
+pinia@^2.0.0-beta.3:
   version "2.0.0-beta.3"
   resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.0-beta.3.tgz#c6f0d07da54dc5aa237f4cc9281898e927b33d16"
   integrity sha512-4ygKhe9FrYD69tJ7nSdgHm9Ldb0aM/Nzyb8Qz/RZuzOyOr85jWHNmCAhCytWy0l9C4/ypGJYCEJ3vuZfyWjcZA==