Commit 327d71b8fb4907ae971d040f6b84bbecb0a6d897
1 parent
941ad597
perf(router): reduce the number of guard files
Showing
21 changed files
with
154 additions
and
177 deletions
.vscode/settings.json
package.json
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
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 'vue-router'; |
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
src/utils/mitt.ts
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== | ... | ... |