优化菜单选中判断逻辑 (#132)

This commit is contained in:
Kerwin Bryant 2022-04-28 11:14:13 +08:00 committed by GitHub
parent 33bdd29561
commit 09c6b17b7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 45 deletions

View File

@ -65,8 +65,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed } from 'vue'; import { PropType, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRouter } from 'vue-router';
import { useSettingStore } from '@/store'; import { useSettingStore } from '@/store';
import { getActive } from '@/router';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import tLogoFull from '@/assets/assets-logo-full.svg?component'; import tLogoFull from '@/assets/assets-logo-full.svg?component';
import { MenuRoute } from '@/interface'; import { MenuRoute } from '@/interface';
@ -115,18 +116,7 @@ const toggleSettingPanel = () => {
}); });
}; };
const active = computed(() => { const active = computed(() => getActive());
const { layout } = props;
const route = useRoute();
if (!route.path) {
return '';
}
return route.path
.split('/')
.filter((item, index) => index < props.maxLevel - (layout === 'mix' ? 1 : -1) && index > 0)
.map((item) => `/${item}`)
.join('');
});
const layoutCls = computed(() => [`${prefix}-header-layout`]); const layoutCls = computed(() => [`${prefix}-header-layout`]);

30
src/layouts/components/MenuContent.tsx Normal file → Executable file
View File

@ -1,6 +1,7 @@
import { defineComponent, PropType, computed, h } from 'vue'; import { defineComponent, PropType, computed, h } from 'vue';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import { MenuRoute } from '@/interface'; import { MenuRoute } from '@/interface';
import { getActive } from '@/router';
const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => { const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
if (!list) { if (!list) {
@ -34,36 +35,33 @@ const renderIcon = (item) => {
return () => ''; return () => '';
}; };
const useRenderNav = (list: Array<MenuRoute>) => { const getPath = (active, item) => {
if (active.startsWith(item.path)) {
return active;
}
return item.meta?.single ? item.redirect : item.path;
};
const useRenderNav = (active: string, list: Array<MenuRoute>) => {
return list.map((item) => { return list.map((item) => {
if (!item.children || !item.children.length || item.meta?.single) { if (!item.children || !item.children.length || item.meta?.single) {
const href = item.path.match(/(http|https):\/\/([\w.]+\/?)\S*/); const href = item.path.match(/(http|https):\/\/([\w.]+\/?)\S*/);
if (href) { if (href) {
return ( return (
<t-menu-item <t-menu-item href={href?.[0]} name={item.path} value={getPath(active, item)} icon={renderIcon(item)}>
href={href?.[0]}
name={item.path}
value={item.meta?.single ? item.redirect : item.path}
icon={renderIcon(item)}
>
{item.title} {item.title}
</t-menu-item> </t-menu-item>
); );
} }
return ( return (
<t-menu-item <t-menu-item name={item.path} value={getPath(active, item)} to={item.path} icon={renderIcon(item)}>
name={item.path}
value={item.meta?.single ? item.redirect : item.path}
to={item.path}
icon={renderIcon(item)}
>
{item.title} {item.title}
</t-menu-item> </t-menu-item>
); );
} }
return ( return (
<t-submenu name={item.path} value={item.path} title={item.title} icon={renderIcon(item)}> <t-submenu name={item.path} value={item.path} title={item.title} icon={renderIcon(item)}>
{item.children && useRenderNav(item.children)} {item.children && useRenderNav(active, item.children)}
</t-submenu> </t-submenu>
); );
}); });
@ -77,6 +75,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const active = computed(() => getActive());
const list = computed(() => { const list = computed(() => {
const { navData } = props; const { navData } = props;
return getMenuList(navData); return getMenuList(navData);
@ -84,11 +83,12 @@ export default defineComponent({
return { return {
prefix, prefix,
active,
list, list,
useRenderNav, useRenderNav,
}; };
}, },
render() { render() {
return <div>{this.useRenderNav(this.list)}</div>; return <div>{this.useRenderNav(this.active, this.list)}</div>;
}, },
}); });

View File

@ -1,17 +1,20 @@
import { defineComponent, PropType, computed, onMounted } from 'vue'; import { defineComponent, PropType, computed, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import pgk from '../../../package.json'; import pgk from '../../../package.json';
import MenuContent from './MenuContent'; import MenuContent from './MenuContent';
import tLogo from '@/assets/assets-t-logo.svg?component'; import tLogo from '@/assets/assets-t-logo.svg?component';
import tLogoFull from '@/assets/assets-logo-full.svg?component'; import tLogoFull from '@/assets/assets-logo-full.svg?component';
import { useSettingStore } from '@/store'; import { useSettingStore } from '@/store';
import { getActive } from '@/router';
const MIN_POINT = 992 - 1; const MIN_POINT = 992 - 1;
const useComputed = (props) => { const useComputed = (props) => {
const collapsed = computed(() => useSettingStore().isSidebarCompact); const collapsed = computed(() => useSettingStore().isSidebarCompact);
const active = computed(() => getActive());
const sideNavCls = computed(() => { const sideNavCls = computed(() => {
const { isCompact } = props; const { isCompact } = props;
return [ return [
@ -40,6 +43,7 @@ const useComputed = (props) => {
}); });
return { return {
active,
collapsed, collapsed,
sideNavCls, sideNavCls,
menuCls, menuCls,
@ -107,18 +111,6 @@ export default defineComponent({
}; };
}); });
const getActiveName = (maxLevel = 2) => {
const route = useRoute();
if (!route.path) {
return '';
}
return route.path
.split('/')
.filter((_item: string, index: number) => index <= maxLevel && index > 0)
.map((item: string) => `/${item}`)
.join('');
};
const goHome = () => { const goHome = () => {
router.push('/dashboard/base'); router.push('/dashboard/base');
}; };
@ -128,18 +120,16 @@ export default defineComponent({
...useComputed(props), ...useComputed(props),
autoCollapsed, autoCollapsed,
changeCollapsed, changeCollapsed,
getActiveName,
goHome, goHome,
}; };
}, },
render() { render() {
const active = this.getActiveName();
return ( return (
<div class={this.sideNavCls}> <div class={this.sideNavCls}>
<t-menu <t-menu
class={this.menuCls} class={this.menuCls}
theme={this.theme} theme={this.theme}
value={active} value={this.active}
collapsed={this.collapsed} collapsed={this.collapsed}
v-slots={{ v-slots={{
logo: () => logo: () =>

View File

@ -1,4 +1,4 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'; import { useRoute, createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import baseRouters from './modules/base'; import baseRouters from './modules/base';
import componentsRouters from './modules/components'; import componentsRouters from './modules/components';
@ -30,6 +30,18 @@ const defaultRouterList: Array<RouteRecordRaw> = [
export const allRoutes = [...defaultRouterList, ...asyncRouterList]; export const allRoutes = [...defaultRouterList, ...asyncRouterList];
export const getActive = (maxLevel = 2): string => {
const route = useRoute();
if (!route.path) {
return '';
}
return route.path
.split('/')
.filter((_item: string, index: number) => index <= maxLevel && index > 0)
.map((item: string) => `/${item}`)
.join('');
};
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes: allRoutes, routes: allRoutes,