提交 327d71b8 编写于 作者: V vben

perf(router): reduce the number of guard files

上级 941ad597
......@@ -129,6 +129,7 @@
"qrcode",
"sider",
"pinia",
"sider"
"sider",
"nprogress"
]
}
......@@ -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';
......
......@@ -137,7 +137,7 @@
watch(
() => props.visible,
(newVal, oldVal) => {
if (newVal != oldVal) visibleRef.value = newVal;
if (newVal !== oldVal) visibleRef.value = newVal;
},
{ deep: true }
);
......
......@@ -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';
......
......@@ -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);
}
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';
......
......@@ -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';
......
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);
......
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;
});
}
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;
});
}
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;
});
}
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);
});
}
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;
});
}
......@@ -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) => {
......
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;
});
}
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;
});
}
......@@ -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;
......
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
export function setupStore(app: App<Element>) {
......
/**
* https://github.com/developit/mitt
* copy to https://github.com/developit/mitt
* Expand clear method
*/
export type EventType = string | symbol;
......
......@@ -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==
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册