基于vue-element-admin的顶部一级导航栏的调整,因为一级路由过多导致其他元素被挤到第二行,故现在将原来一级路由数组拆分成两个数组,第二个数组以子菜单显示
关键处调整代码
html
html
<el-menu
:active-text-color="variables.menuActiveText"
:default-active="activeMenu"
mode="horizontal"
@select="handleSelect"
>
<div v-for="item in displayedRoutes" :key="item.path" class="nav-item">
<app-link :to="resolvePath(item)">
<el-menu-item v-if="!item.hidden" :index="item.path">
<i
:class="
item.meta && item.meta.icon ? item.meta.icon : 'el-icon-house'
"
></i>
{{
item.meta ? item.meta.title : item.children[0].meta.title
}}</el-menu-item
>
</app-link>
</div>
<el-submenu v-if="hiddenRoutes.length > 0" index="coll">
<template slot="title"><i class="el-icon-more"></i></template>
<div v-for="item in hiddenRoutes" :key="item.path" class="nav-item">
<app-link :to="resolvePath(item)">
<el-menu-item v-if="!item.hidden" :index="item.path">
<i
:class="
item.meta && item.meta.icon ? item.meta.icon : 'el-icon-house'
"
></i>
{{
item.meta ? item.meta.title : item.children[0].meta.title
}}</el-menu-item
>
</app-link>
</div>
</el-submenu>
</el-menu>
js
javascript
export default {
name: "Topbar",
components: {
AppLink,
},
data() {
return {
activeIndex: "1",
logo: titlePng,
// avatar: sessionStorage.getItem("avatar"),
routes: constantRoutes,
};
},
computed: {
...mapGetters(["permission_routes", "async_routes", "avatar"]),
activeMenu() {
const route = this.$route;
const { meta, path } = route;
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu;
}
// 如果是首页,首页高亮
if (path === "/dashboard") {
return "/";
}
// 如果不是首页,高亮一级菜单
const activeMenu = "/" + path.split("/")[1];
return activeMenu;
},
variables() {
return variables;
},
sidebar() {
return this.$store.state.app.sidebar;
},
displayedRoutes() {
// 这里可以根据需要定义展示的路由项
return this.routes.slice(0, 9); // 例如,展示前 9 个路由
},
hiddenRoutes() {
// 返回剩余的路由项
const hidden = this.routes.slice(9); // 省略的路由项
return hidden.length > 0 ? hidden : []; // 只有在有省略项时返回
},
},
watch: {
activeMenu(newVal, oldVal) {
this.handleSelect(newVal);
},
},
mounted() {
this.initCurrentRoutes();
},
methods: {
// 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单
initCurrentRoutes() {
this.$router.addRoutes(this.async_routes);
this.routes = this.permission_routes; // 动态路由赋值
const { path } = this.$route;
let route = this.routes.find(
(item) => item.path === "/" + path.split("/")[1]
);
// 如果找不到这个路由,说明是首页
if (!route) {
route = this.routes.find((item) => item.path === "/");
}
this.$store.commit("permission/SET_CURRENT_ROUTES", route);
this.setSidebarHide(route);
},
// 判断该路由是否只有一个子项或者没有子项,如果是,则在一级菜单添加跳转路由
isOnlyOneChild(item) {
if (item.children && item.children.length === 1) {
return true;
}
return false;
},
resolvePath(item) {
// 如果是个完成的url直接返回
if (isExternal(item.path)) {
return item.path;
}
// 如果是首页,就返回重定向路由
if (item.path === "/") {
const path = item.redirect;
return path;
}
// 如果有子项,默认跳转第一个子项路由
let path = "";
/**
* item 路由子项
* parent 路由父项
*/
const getDefaultPath = (item, parent) => {
// 如果path是个外部链接(不建议),直接返回链接,存在个问题:如果是外部链接点击跳转后当前页内容还是上一个路由内容
if (isExternal(item.path)) {
path = item.path;
return;
}
// 第一次需要父项路由拼接,所以只是第一个传parent
if (parent) {
path += parent.path + "/" + item.path;
} else {
path += "/" + item.path;
}
// 如果还有子项,继续递归
if (item.children) {
getDefaultPath(item.children[0]);
}
};
if (item.children) {
getDefaultPath(item.children[0], item);
return path;
}
return item.path;
},
handleSelect(key, keyPath) {
// 把选中路由的子路由保存store
const route = this.routes.find((item) => item.path === key);
this.$store.commit("permission/SET_CURRENT_ROUTES", route);
this.setSidebarHide(route);
},
// 设置侧边栏的显示和隐藏
setSidebarHide(route) {
if (!route.children || route.children.length === 1) {
this.$store.dispatch("app/toggleSideBarHide", true);
} else {
this.$store.dispatch("app/toggleSideBarHide", false);
}
},
async logout() {
await this.$store.dispatch("user/logout");
this.$router.push(`/login?redirect=${this.$route.fullPath}`);
},
toggleFullScreen() {
// 检查浏览器是否支持全屏 API
if (screenfull.isEnabled) {
screenfull.toggle(); // 切换全屏模式
} else {
console.warn("该浏览器不支持全屏");
}
},
},
};
</script>
拆分逻辑是如果数组长度超过九个就拆分。如果想要根据不同浏览器窗口大小去拆分显示,需要去监听浏览器的实时宽度,计算整行所有元素的长度总和,如果超出则将超出的路由加入子菜单中显示