Commit 327d71b8fb4907ae971d040f6b84bbecb0a6d897

Authored by vben
1 parent 941ad597

perf(router): reduce the number of guard files

.vscode/settings.json
... ... @@ -129,6 +129,7 @@
129 129 "qrcode",
130 130 "sider",
131 131 "pinia",
132   - "sider"
  132 + "sider",
  133 + "nprogress"
133 134 ]
134 135 }
... ...
package.json
... ... @@ -50,7 +50,7 @@
50 50 "mockjs": "^1.1.0",
51 51 "nprogress": "^0.2.0",
52 52 "path-to-regexp": "^6.2.0",
53   - "pinia": "2.0.0-beta.3",
  53 + "pinia": "^2.0.0-beta.3",
54 54 "print-js": "^1.6.0",
55 55 "qrcode": "^1.4.4",
56 56 "sortablejs": "^1.13.0",
... ...
src/App.vue
... ... @@ -10,7 +10,6 @@
10 10 import { defineComponent } from 'vue';
11 11 import { ConfigProvider } from 'ant-design-vue';
12 12 import { AppProvider } from '/@/components/Application';
13   -
14 13 import { useTitle } from '/@/hooks/web/useTitle';
15 14 import { useLocale } from '/@/locales/useLocale';
16 15  
... ...
src/components/Drawer/src/BasicDrawer.vue
... ... @@ -137,7 +137,7 @@
137 137 watch(
138 138 () => props.visible,
139 139 (newVal, oldVal) => {
140   - if (newVal != oldVal) visibleRef.value = newVal;
  140 + if (newVal !== oldVal) visibleRef.value = newVal;
141 141 },
142 142 { deep: true }
143 143 );
... ...
src/components/Menu/src/BasicMenu.vue
... ... @@ -19,25 +19,18 @@
19 19 </template>
20 20 <script lang="ts">
21 21 import type { MenuState } from './types';
22   -
23 22 import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
24 23 import { Menu } from 'ant-design-vue';
25 24 import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
26   -
27 25 import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
28   -
29 26 import { useOpenKeys } from './useOpenKeys';
30 27 import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
31   -
32 28 import { isFunction } from '/@/utils/is';
33   -
34 29 import { basicProps } from './props';
35 30 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
36 31 import { REDIRECT_NAME } from '/@/router/constant';
37 32 import { useDesign } from '/@/hooks/web/useDesign';
38   -
39 33 import { getCurrentParentPath } from '/@/router/menus';
40   -
41 34 import { listenerRouteChange } from '/@/logics/mitt/routeChange';
42 35 import { getAllParentPath } from '/@/router/helper/menuHelper';
43 36  
... ...
src/components/registerGlobComp.ts
... ... @@ -5,6 +5,7 @@ import {
5 5 // Need
6 6 Button as AntButton,
7 7 Input,
  8 + Layout,
8 9 } from 'ant-design-vue';
9 10  
10 11 const compList = [AntButton.Group];
... ... @@ -14,5 +15,5 @@ export function registerGlobComp(app: App) {
14 15 app.component(comp.name || comp.displayName, comp);
15 16 });
16 17  
17   - app.use(Input).use(Button);
  18 + app.use(Input).use(Button).use(Layout);
18 19 }
... ...
src/layouts/default/menu/useLayoutMenu.ts
1 1 import type { Menu } from '/@/router/types';
2 2 import type { Ref } from 'vue';
3   -
4 3 import { watch, unref, ref, computed } from 'vue';
5 4 import { useRouter } from 'vue-router';
6   -
7 5 import { MenuSplitTyeEnum } from '/@/enums/menuEnum';
8 6 import { useThrottleFn } from '@vueuse/core';
9 7 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
10   -
11 8 import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
12 9 import { usePermissionStore } from '/@/store/modules/permission';
13 10 import { useAppInject } from '/@/hooks/web/useAppInject';
... ...
src/layouts/default/sider/MixSider.vue
... ... @@ -81,24 +81,19 @@
81 81 import type { Menu } from '/@/router/types';
82 82 import type { CSSProperties } from 'vue';
83 83 import type { RouteLocationNormalized } from 'vue-router';
84   -
85 84 import { defineComponent, onMounted, ref, computed, unref } from 'vue';
86   -
87 85 import { ScrollContainer } from '/@/components/Container';
88 86 import { SimpleMenuTag } from '/@/components/SimpleMenu';
89 87 import { Icon } from '/@/components/Icon';
90 88 import { AppLogo } from '/@/components/Application';
91 89 import Trigger from '../trigger/HeaderTrigger.vue';
92   -
93 90 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
94 91 import { useDragLine } from './useLayoutSider';
95 92 import { useGlobSetting } from '/@/hooks/setting';
96 93 import { useDesign } from '/@/hooks/web/useDesign';
97 94 import { useI18n } from '/@/hooks/web/useI18n';
98 95 import { useGo } from '/@/hooks/web/usePage';
99   -
100 96 import { SIDE_BAR_SHOW_TIT_MINI_WIDTH, SIDE_BAR_MINI_WIDTH } from '/@/enums/appEnum';
101   -
102 97 import clickOutside from '/@/directives/clickOutside';
103 98 import { getShallowMenus, getChildrenMenus, getCurrentParentPath } from '/@/router/menus';
104 99 import { listenerRouteChange } from '/@/logics/mitt/routeChange';
... ...
src/main.ts
1 1 import '/@/design/index.less';
2 2 import '/@/design/tailwind.css';
3   -
4 3 // Register icon sprite
5 4 import 'virtual:svg-icons-register';
6   -
7 5 import App from './App.vue';
8 6 import { createApp } from 'vue';
9 7 import { initAppConfigStore } from '/@/logics/initAppConfig';
... ... @@ -42,7 +40,7 @@ async function bootstrap() {
42 40 setupRouter(app);
43 41  
44 42 // router-guard
45   - setupRouterGuard();
  43 + setupRouterGuard(router);
46 44  
47 45 // Register global directive
48 46 setupGlobDirectives(app);
... ...
src/router/guard/httpGuard.ts deleted 100644 → 0
1   -import type { Router } from 'vue-router';
2   -import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
3   -import projectSetting from '/@/settings/projectSetting';
4   -
5   -/**
6   - * The interface used to close the current page to complete the request when the route is switched
7   - * @param router
8   - */
9   -export function createHttpGuard(router: Router) {
10   - const { removeAllHttpPending } = projectSetting;
11   - let axiosCanceler: Nullable<AxiosCanceler>;
12   - if (removeAllHttpPending) {
13   - axiosCanceler = new AxiosCanceler();
14   - }
15   - router.beforeEach(async () => {
16   - // Switching the route will delete the previous request
17   - axiosCanceler?.removeAllPending();
18   - return true;
19   - });
20   -}
src/router/guard/index.ts
1   -import { router } from '/@/router';
2   -
3   -import { createProgressGuard } from './progressGuard';
  1 +import type { Router, RouteLocationNormalized } from 'vue-router';
  2 +import { useAppStoreWidthOut } from '/@/store/modules/app';
  3 +import { useUserStoreWidthOut } from '/@/store/modules/user';
  4 +import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
  5 +import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
  6 +import { Modal, notification } from 'ant-design-vue';
  7 +import { warn } from '/@/utils/log';
  8 +import { unref } from 'vue';
  9 +import { setRouteChange } from '/@/logics/mitt/routeChange';
4 10 import { createPermissionGuard } from './permissionGuard';
5   -import { createPageLoadingGuard } from './pageLoadingGuard';
6   -import { createMessageGuard } from './messageGuard';
7   -import { createScrollGuard } from './scrollGuard';
8   -import { createHttpGuard } from './httpGuard';
9   -import { createPageGuard } from './pageGuard';
10 11 import { createStateGuard } from './stateGuard';
  12 +import nProgress from 'nprogress';
  13 +import projectSetting from '/@/settings/projectSetting';
11 14  
12   -export function setupRouterGuard() {
  15 +// Don't change the order of creation
  16 +export function setupRouterGuard(router: Router) {
13 17 createPageGuard(router);
14 18 createPageLoadingGuard(router);
15 19 createHttpGuard(router);
... ... @@ -19,3 +23,123 @@ export function setupRouterGuard() {
19 23 createPermissionGuard(router);
20 24 createStateGuard(router);
21 25 }
  26 +
  27 +/**
  28 + * Hooks for handling page state
  29 + */
  30 +function createPageGuard(router: Router) {
  31 + const loadedPageMap = new Map<string, boolean>();
  32 +
  33 + router.beforeEach(async (to) => {
  34 + // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
  35 + to.meta.loaded = !!loadedPageMap.get(to.path);
  36 + // Notify routing changes
  37 + setRouteChange(to);
  38 +
  39 + return true;
  40 + });
  41 +
  42 + router.afterEach((to) => {
  43 + loadedPageMap.set(to.path, true);
  44 + });
  45 +}
  46 +
  47 +// Used to handle page loading status
  48 +function createPageLoadingGuard(router: Router) {
  49 + const userStore = useUserStoreWidthOut();
  50 + const appStore = useAppStoreWidthOut();
  51 + const { getOpenPageLoading } = useTransitionSetting();
  52 + router.beforeEach(async (to) => {
  53 + if (!userStore.getToken) {
  54 + return true;
  55 + }
  56 + if (to.meta.loaded) {
  57 + return true;
  58 + }
  59 +
  60 + if (unref(getOpenPageLoading)) {
  61 + appStore.setPageLoadingAction(true);
  62 + return true;
  63 + }
  64 +
  65 + return true;
  66 + });
  67 + router.afterEach(async () => {
  68 + if (unref(getOpenPageLoading)) {
  69 + // TODO Looking for a better way
  70 + // The timer simulates the loading time to prevent flashing too fast,
  71 + setTimeout(() => {
  72 + appStore.setPageLoading(false);
  73 + }, 220);
  74 + }
  75 + return true;
  76 + });
  77 +}
  78 +
  79 +/**
  80 + * The interface used to close the current page to complete the request when the route is switched
  81 + * @param router
  82 + */
  83 +function createHttpGuard(router: Router) {
  84 + const { removeAllHttpPending } = projectSetting;
  85 + let axiosCanceler: Nullable<AxiosCanceler>;
  86 + if (removeAllHttpPending) {
  87 + axiosCanceler = new AxiosCanceler();
  88 + }
  89 + router.beforeEach(async () => {
  90 + // Switching the route will delete the previous request
  91 + axiosCanceler?.removeAllPending();
  92 + return true;
  93 + });
  94 +}
  95 +
  96 +// Routing switch back to the top
  97 +function createScrollGuard(router: Router) {
  98 + const isHash = (href: string) => {
  99 + return /^#/.test(href);
  100 + };
  101 +
  102 + const body = document.body;
  103 +
  104 + router.afterEach(async (to) => {
  105 + // scroll top
  106 + isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
  107 + return true;
  108 + });
  109 +}
  110 +
  111 +/**
  112 + * Used to close the message instance when the route is switched
  113 + * @param router
  114 + */
  115 +export function createMessageGuard(router: Router) {
  116 + const { closeMessageOnSwitch } = projectSetting;
  117 +
  118 + router.beforeEach(async () => {
  119 + try {
  120 + if (closeMessageOnSwitch) {
  121 + Modal.destroyAll();
  122 + notification.destroy();
  123 + }
  124 + } catch (error) {
  125 + warn('message guard error:' + error);
  126 + }
  127 + return true;
  128 + });
  129 +}
  130 +
  131 +export function createProgressGuard(router: Router) {
  132 + const { getOpenNProgress } = useTransitionSetting();
  133 + router.beforeEach(async (to) => {
  134 + if (to.meta.loaded) {
  135 + return true;
  136 + }
  137 + unref(getOpenNProgress) && nProgress.start();
  138 + return true;
  139 + });
  140 +
  141 + router.afterEach(async () => {
  142 + unref(getOpenNProgress) && nProgress.done();
  143 + return true;
  144 + });
  145 +}
... ...
src/router/guard/messageGuard.ts deleted 100644 → 0
1   -import type { Router } from 'vue-router';
2   -import { Modal, notification } from 'ant-design-vue';
3   -import projectSetting from '/@/settings/projectSetting';
4   -import { warn } from '/@/utils/log';
5   -
6   -/**
7   - * Used to close the message instance when the route is switched
8   - * @param router
9   - */
10   -export function createMessageGuard(router: Router) {
11   - const { closeMessageOnSwitch } = projectSetting;
12   -
13   - router.beforeEach(async () => {
14   - try {
15   - if (closeMessageOnSwitch) {
16   - Modal.destroyAll();
17   - notification.destroy();
18   - }
19   - } catch (error) {
20   - warn('message guard error:' + error);
21   - }
22   - return true;
23   - });
24   -}
src/router/guard/pageGuard.ts deleted 100644 → 0
1   -import type { Router } from 'vue-router';
2   -import { setRouteChange } from '/@/logics/mitt/routeChange';
3   -
4   -export function createPageGuard(router: Router) {
5   - const loadedPageMap = new Map<string, boolean>();
6   -
7   - router.beforeEach(async (to) => {
8   - to.meta.loaded = !!loadedPageMap.get(to.path);
9   - // Notify routing changes
10   - setRouteChange(to);
11   -
12   - return true;
13   - });
14   -
15   - router.afterEach((to) => {
16   - loadedPageMap.set(to.path, true);
17   - });
18   -}
src/router/guard/pageLoadingGuard.ts deleted 100644 → 0
1   -import type { Router } from 'vue-router';
2   -import { useAppStoreWidthOut } from '/@/store/modules/app';
3   -import { useUserStoreWidthOut } from '/@/store/modules/user';
4   -import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
5   -import { unref } from 'vue';
6   -
7   -export function createPageLoadingGuard(router: Router) {
8   - const userStore = useUserStoreWidthOut();
9   - const appStore = useAppStoreWidthOut();
10   - const { getOpenPageLoading } = useTransitionSetting();
11   - router.beforeEach(async (to) => {
12   - if (!userStore.getToken) {
13   - return true;
14   - }
15   - if (to.meta.loaded) {
16   - return true;
17   - }
18   -
19   - if (unref(getOpenPageLoading)) {
20   - appStore.setPageLoadingAction(true);
21   - return true;
22   - }
23   -
24   - return true;
25   - });
26   - router.afterEach(async () => {
27   - if (unref(getOpenPageLoading)) {
28   - setTimeout(() => {
29   - appStore.setPageLoading(false);
30   - }, 220);
31   - }
32   - return true;
33   - });
34   -}
src/router/guard/permissionGuard.ts
... ... @@ -32,13 +32,11 @@ export function createPermissionGuard(router: Router) {
32 32 // token does not exist
33 33 if (!token) {
34 34 // You can access without permission. You need to set the routing meta.ignoreAuth to true
35   - if (
36   - to.meta.ignoreAuth
37   - // || to.name === FULL_PAGE_NOT_FOUND_ROUTE.name
38   - ) {
  35 + if (to.meta.ignoreAuth) {
39 36 next();
40 37 return;
41 38 }
  39 +
42 40 // redirect login page
43 41 const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
44 42 path: LOGIN_PATH,
... ... @@ -53,10 +51,12 @@ export function createPermissionGuard(router: Router) {
53 51 next(redirectData);
54 52 return;
55 53 }
  54 +
56 55 if (permissionStore.getIsDynamicAddedRoute) {
57 56 next();
58 57 return;
59 58 }
  59 +
60 60 const routes = await permissionStore.buildRoutesAction();
61 61  
62 62 routes.forEach((route) => {
... ...
src/router/guard/progressGuard.ts deleted 100644 → 0
1   -import type { Router } from 'vue-router';
2   -
3   -import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
4   -
5   -import nProgress from 'nprogress';
6   -
7   -import { unref } from 'vue';
8   -
9   -export function createProgressGuard(router: Router) {
10   - const { getOpenNProgress } = useTransitionSetting();
11   - router.beforeEach(async (to) => {
12   - if (to.meta.loaded) return true;
13   - unref(getOpenNProgress) && nProgress.start();
14   - return true;
15   - });
16   -
17   - router.afterEach(async () => {
18   - // if (to.meta.loaded) return true;
19   - unref(getOpenNProgress) && nProgress.done();
20   - return true;
21   - });
22   -}
src/router/guard/scrollGuard.ts deleted 100644 → 0
1   -import type { RouteLocationNormalized, Router } from 'vue-router';
2   -
3   -const isHash = (href: string) => {
4   - return /^#/.test(href);
5   -};
6   -
7   -export function createScrollGuard(router: Router) {
8   - const body = document.body;
9   -
10   - router.afterEach(async (to) => {
11   - // scroll top
12   - isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0);
13   - return true;
14   - });
15   -}
src/router/helper/routeHelper.ts
... ... @@ -9,7 +9,7 @@ import { createRouter, createWebHashHistory } from &#39;vue-router&#39;;
9 9 export type LayoutMapKey = 'LAYOUT';
10 10 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
11 11  
12   -const LayoutMap = new Map<String, () => Promise<typeof import('*.vue')>>();
  12 +const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
13 13  
14 14 LayoutMap.set('LAYOUT', LAYOUT);
15 15 LayoutMap.set('IFRAME', IFRAME);
... ... @@ -27,7 +27,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
27 27 const { component, name } = item;
28 28 const { children } = item;
29 29 if (component) {
30   - const layoutFound = LayoutMap.get(component);
  30 + const layoutFound = LayoutMap.get(component as string);
31 31 if (layoutFound) {
32 32 item.component = layoutFound;
33 33 } else {
... ... @@ -66,10 +66,10 @@ function dynamicImport(
66 66 // Turn background objects into routing objects
67 67 export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
68 68 routeList.forEach((route) => {
69   - if (route.component) {
70   - if ((route.component as string).toUpperCase() === 'LAYOUT') {
71   - //route.component = LayoutMap.get(route.component as LayoutMapKey);
72   - route.component = LayoutMap.get((route.component as string).toUpperCase() as LayoutMapKey);
  69 + const component = route.component as string;
  70 + if (component) {
  71 + if (component.toUpperCase() === 'LAYOUT') {
  72 + route.component = LayoutMap.get(component.toUpperCase());
73 73 } else {
74 74 route.children = [cloneDeep(route)];
75 75 route.component = LAYOUT;
... ...
src/store/index.ts
1 1 import type { App } from 'vue';
2 2 import { createPinia } from 'pinia';
  3 +
3 4 const store = createPinia();
4 5  
5 6 export function setupStore(app: App<Element>) {
... ...
src/utils/mitt.ts
1 1 /**
2   - * https://github.com/developit/mitt
  2 + * copy to https://github.com/developit/mitt
  3 + * Expand clear method
3 4 */
4 5  
5 6 export type EventType = string | symbol;
... ...
yarn.lock
... ... @@ -9278,7 +9278,7 @@ pify@^4.0.1:
9278 9278 resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
9279 9279 integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
9280 9280  
9281   -pinia@2.0.0-beta.3:
  9281 +pinia@^2.0.0-beta.3:
9282 9282 version "2.0.0-beta.3"
9283 9283 resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.0-beta.3.tgz#c6f0d07da54dc5aa237f4cc9281898e927b33d16"
9284 9284 integrity sha512-4ygKhe9FrYD69tJ7nSdgHm9Ldb0aM/Nzyb8Qz/RZuzOyOr85jWHNmCAhCytWy0l9C4/ypGJYCEJ3vuZfyWjcZA==
... ...