Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: 页面切换性能优化 #600

Merged
merged 2 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions src/layout/components/sidebar/horizontal.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, nextTick } from "vue";
import Search from "../search/index.vue";
import Notice from "../notice/index.vue";
import { ref, watch, nextTick } from "vue";
import SidebarItem from "./sidebarItem.vue";
import { useNav } from "@/layout/hooks/useNav";
import { useTranslationLang } from "../../hooks/useTranslationLang";
Expand All @@ -17,11 +17,9 @@ const { t, route, locale, translationCh, translationEn } =
useTranslationLang(menuRef);
const {
title,
routers,
logout,
backTopMenu,
onPanel,
menuSelect,
username,
userAvatar,
avatarsStyle,
Expand All @@ -32,13 +30,6 @@ const {
nextTick(() => {
menuRef.value?.handleResize();
});

watch(
() => route.path,
() => {
menuSelect(route.path, routers);
}
);
</script>

<template>
Expand All @@ -56,7 +47,6 @@ watch(
mode="horizontal"
class="horizontal-header-menu"
:default-active="route.path"
@select="indexPath => menuSelect(indexPath, routers)"
>
<sidebar-item
v-for="route in usePermissionStoreHook().wholeMenus"
Expand Down
3 changes: 0 additions & 3 deletions src/layout/components/sidebar/mixNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ const { t, route, locale, translationCh, translationEn } =
useTranslationLang(menuRef);
const {
device,
routers,
logout,
onPanel,
menuSelect,
resolvePath,
username,
userAvatar,
Expand Down Expand Up @@ -72,7 +70,6 @@ watch(
mode="horizontal"
class="horizontal-header-menu"
:default-active="defaultActive"
@select="indexPath => menuSelect(indexPath, routers)"
>
<el-menu-item
v-for="route in usePermissionStoreHook().wholeMenus"
Expand Down
6 changes: 2 additions & 4 deletions src/layout/components/sidebar/vertical.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ const showLogo = ref(
)?.showLogo ?? true
);

const { routers, device, pureApp, isCollapse, menuSelect, toggleSideBar } =
useNav();
const { device, pureApp, isCollapse, menuSelect, toggleSideBar } = useNav();

const subMenuData = ref([]);

Expand Down Expand Up @@ -56,7 +55,7 @@ watch(
() => {
if (route.path.includes("/redirect")) return;
getSubMenuData(route.path);
menuSelect(route.path, routers);
menuSelect(route.path);
}
);

Expand Down Expand Up @@ -90,7 +89,6 @@ onBeforeUnmount(() => {
:collapse="isCollapse"
:default-active="route.path"
:collapse-transition="false"
@select="indexPath => menuSelect(indexPath, routers)"
>
<sidebar-item
v-for="routes in menuData"
Expand Down
39 changes: 17 additions & 22 deletions src/layout/components/tag/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { emitter } from "@/utils/mitt";
import { RouteConfigs } from "../../types";
import { useTags } from "../../hooks/useTag";
import { routerArrays } from "@/layout/types";
import { isEqual, isAllEmpty } from "@pureadmin/utils";
import { handleAliveRoute, getTopMenu } from "@/router/utils";
import { useSettingStoreHook } from "@/store/modules/settings";
import { useResizeObserver, useFullscreen } from "@vueuse/core";
import { isEqual, isAllEmpty, debounce } from "@pureadmin/utils";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { ref, watch, unref, toRaw, nextTick, onBeforeUnmount } from "vue";
import { useResizeObserver, useDebounceFn, useFullscreen } from "@vueuse/core";

import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
Expand Down Expand Up @@ -54,20 +54,22 @@ const topPath = getTopMenu()?.path;
const { VITE_HIDE_HOME } = import.meta.env;
const { isFullscreen, toggle } = useFullscreen();

const dynamicTagView = () => {
const dynamicTagView = async () => {
await nextTick();
const index = multiTags.value.findIndex(item => {
if (item.query) {
if (!isAllEmpty(route.query)) {
return isEqual(route.query, item.query);
} else if (item.params) {
} else if (!isAllEmpty(route.params)) {
return isEqual(route.params, item.params);
} else {
return item.path === route.path;
return route.path === item.path;
}
});
moveToView(index);
};

const moveToView = async (index: number): Promise<void> => {
await nextTick();
const tabNavPadding = 10;
if (!instance.refs["dynamic" + index]) return;
const tabItemEl = instance.refs["dynamic" + index][0];
Expand All @@ -78,9 +80,6 @@ const moveToView = async (index: number): Promise<void> => {
? scrollbarDom.value?.offsetWidth
: 0;

// 获取视图更新后dom
await nextTick();

// 已有标签页总长度(包含溢出部分)
const tabDomWidth = tabDom.value ? tabDom.value?.offsetWidth : 0;

Expand Down Expand Up @@ -135,31 +134,29 @@ const handleScroll = (offset: number): void => {
}
};

function dynamicRouteTag(value: string, parentPath: string): void {
function dynamicRouteTag(value: string): void {
const hasValue = multiTags.value.some(item => {
return item.path === value;
});

function concatPath(arr: object[], value: string, parentPath: string) {
function concatPath(arr: object[], value: string) {
if (!hasValue) {
arr.forEach((arrItem: any) => {
const pathConcat = parentPath + arrItem.path;
if (arrItem.path === value || pathConcat === value) {
if (arrItem.path === value || arrItem.path === value) {
useMultiTagsStoreHook().handleTags("push", {
path: value,
parentPath: `/${parentPath.split("/")[1]}`,
meta: arrItem.meta,
name: arrItem.name
});
} else {
if (arrItem.children && arrItem.children.length > 0) {
concatPath(arrItem.children, value, parentPath);
concatPath(arrItem.children, value);
}
}
});
}
}
concatPath(router.options.routes as any, value, parentPath);
concatPath(router.options.routes as any, value);
}

/** 刷新路由 */
Expand Down Expand Up @@ -465,7 +462,7 @@ function tagOnClick(item) {
// showMenuModel(item?.path, item?.query);
}

watch([route], () => {
watch(route, () => {
activeIndex.value = -1;
dynamicTagView();
});
Expand Down Expand Up @@ -493,18 +490,16 @@ onMounted(() => {
});

// 接收侧边栏切换传递过来的参数
emitter.on("changLayoutRoute", ({ indexPath, parentPath }) => {
dynamicRouteTag(indexPath, parentPath);
emitter.on("changLayoutRoute", indexPath => {
dynamicRouteTag(indexPath);
setTimeout(() => {
showMenuModel(indexPath);
});
});

useResizeObserver(
scrollbarDom,
useDebounceFn(() => {
dynamicTagView();
}, 200)
debounce(() => dynamicTagView())
);
});

Expand Down
33 changes: 4 additions & 29 deletions src/layout/hooks/useNav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,38 +114,13 @@ export function useNav() {
}
}

function menuSelect(indexPath: string, routers): void {
if (wholeMenus.value.length === 0) return;
if (isRemaining(indexPath)) return;
let parentPath = "";
const parentPathIndex = indexPath.lastIndexOf("/");
if (parentPathIndex > 0) {
parentPath = indexPath.slice(0, parentPathIndex);
}
/** 找到当前路由的信息 */
function findCurrentRoute(indexPath: string, routes) {
if (!routes) return console.error(errorInfo);
return routes.map(item => {
if (item.path === indexPath) {
if (item.redirect) {
findCurrentRoute(item.redirect, item.children);
} else {
/** 切换左侧菜单 通知标签页 */
emitter.emit("changLayoutRoute", {
indexPath,
parentPath
});
}
} else {
if (item.children) findCurrentRoute(indexPath, item.children);
}
});
}
findCurrentRoute(indexPath, routers);
function menuSelect(indexPath: string) {
if (wholeMenus.value.length === 0 || isRemaining(indexPath)) return;
emitter.emit("changLayoutRoute", indexPath);
}

/** 判断路径是否参与菜单 */
function isRemaining(path: string): boolean {
function isRemaining(path: string) {
return remainingPaths.includes(path);
}

Expand Down
2 changes: 0 additions & 2 deletions src/layout/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export const routerArrays: Array<RouteConfigs> =
? [
{
path: "/welcome",
parentPath: "/",
meta: {
title: "menus.hshome",
icon: "homeFilled"
Expand All @@ -25,7 +24,6 @@ export type routeMetaType = {

export type RouteConfigs = {
path?: string;
parentPath?: string;
query?: object;
params?: object;
meta?: routeMetaType;
Expand Down
3 changes: 2 additions & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ router.beforeEach((to: toRouteType, _from, next) => {
}
}
}
router.push(to.fullPath);
// 确保动态路由完全加入路由列表并且不影响静态路由(注意:动态路由刷新时router.beforeEach可能会触发两次,第一次触发动态路由还未完全添加,第二次动态路由才完全添加到路由列表,如果需要在router.beforeEach做一些判断可以在to.name存在的条件下去判断,这样就只会触发一次)
if (isAllEmpty(to.name)) router.push(to.fullPath);
});
}
toCorrectRoute();
Expand Down
1 change: 0 additions & 1 deletion src/store/modules/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export type appType = {

export type multiType = {
path: string;
parentPath: string;
name: string;
meta: any;
query?: object;
Expand Down
12 changes: 2 additions & 10 deletions src/utils/mitt.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import type { Emitter } from "mitt";
import mitt from "mitt";

/** 全局公共事件需要在此处添加类型 */
type Events = {
resize: {
detail: {
width: number;
height: number;
};
};
openPanel: string;
tagViewsChange: string;
tagViewsShowModel: string;
logoChange: boolean;
changLayoutRoute: {
indexPath: string;
parentPath: string;
};
changLayoutRoute: string;
};

export const emitter: Emitter<Events> = mitt<Events>();