若依菜单改造(一):侧边栏显示不同菜单组
需求
点击菜单上某个图标,侧边栏的菜单项内容进行切换。效果如下:
拆解需求:
-
副标题:居中、可切换
-
副标题下的菜单内容可切换。
解决思路
若依的菜单设置分为两种:
- 在
菜单管理
中设置 - 在
router.js
中书写公共路由或动态路由(根据用户权限加载)
此处应该设置动态路由,方便根据用户权限加载。
若在 菜单管理
中设置,无法令菜单内容可切换;因此,只能在router.js
中书写动态路由。
重点
- 副标题样式可参照标题,只不过文本内容居中。
- 菜单组内容切换,可给
el-menu
传入不同的内容项,通过Vuex
实现点击切换。
代码
副标题代码
MenuTitle组件
<div
class="menu-title-container"
:class="{ collapse: collapse }"
:style="{
backgroundColor:
sideTheme === 'theme-dark'
? variables.menuBackground
: variables.menuLightBackground,
}"
>
<transition name="menuTitleFade">
<router-link
v-if="collapse"
key="collapse"
class="menu-title-link"
:to="indexLink"
>
<img v-if="logo" :src="logo" class="menu-title-logo" />
<h1
v-else
class="menu-title"
:style="{
color:
sideTheme === 'theme-dark'
? variables.logoTitleColor
: variables.logoLightTitleColor,
}"
>
{{ title }}
</h1>
</router-link>
<router-link v-else key="expand" class="menu-title-link" :to="indexLink">
<img v-if="logo" :src="logo" class="menu-title-logo" />
<h1
class="menu-title"
:style="{
color:
sideTheme === 'theme-dark'
? variables.logoTitleColor
: variables.logoLightTitleColor,
}"
>
{{ title }}
</h1>
</router-link>
</transition>
</div>
菜单组代码
SideBar/index.vue
computed: {
// 其他代码
...mapState(["settings"]),
...mapGetters([
"sidebarRouters",
"sidebar",
"menuBarIndex",
"menuProjectId",
]),
menuBarList() {
return [
{
title: "系统空间",
indexLink: "/projects/projectList",
menus: this.sidebarRouters.filter(
(ele) =>
!ele.meta ||
!ele.meta.menuTitle ||
ele.meta.menuTitle !== "项目空间"
),
},
{
title: "项目空间",
indexLink: `/project/pro-index?projectId=${this.menuProjectId}`,
menus: this.ProTitleMenus,
},
];
},
ProTitleMenus() {
let res = this.sidebarRouters.filter(
(ele) => ele.meta && ele.meta.menuTitle === "项目空间"
);
this.loopAdd(res);
return res;
},
},
怎样区分不同的菜单组?——给路由的元信息添加 menuTitle
标记
此处 系统空间
的路由是在 菜单管理
中配置的,那么 项目空间
的路由就在 router.js
中手动书写。
`router.js` 中配置路由
// 动态路由:加上 permissions 配置项即可
/* === 项目空间路由 start === */
// 项目首页
{
path: `/project`,
component: Layout,
// redirect: "noRedirect",
meta: {
menuTitle: `项目空间`,
},
children: [
{
path: "pro-index",
component: () =>
import(/* webpackChunkName: 'proIndex' */ "@/views/pro-index/index"),
name: "ProIndex",
meta: {
title: `项目首页`,
icon: "dashboard",
activeMenu: `/project/pro-index`,
},
},
],
},
// 组织管理
{
path: "/project/organize",
component: Layout,
redirect: "noRedirect",
meta: {
menuTitle: `项目空间`,
title: `组织管理`,
icon: "cascader",
},
alwaysShow: true,
children: [
{
path: "pro-role",
component: () =>
import(
/* webpackChunkName: 'proRole' */ "@/views/organize/pro-role/index.vue"
),
name: "ProRole",
meta: {
title: `项目角色`,
icon: "peoples",
},
},
{
path: "pro-user/:roleId(\\d+)",
hidden: true,
component: () => import("@/views/organize/pro-role/proAuthUser"),
name: "ProAuthUser",
meta: { title: "分配用户" },
},
],
},
// 项目配置
{
path: "/project/pro-config",
component: Layout,
redirect: "noRedirect",
meta: {
menuTitle: `项目空间`,
title: `项目配置`,
icon: "system",
},
alwaysShow: true,
children: [
{
path: "pro-setting",
component: () =>
import(
/* webpackChunkName: 'proSetting' */ "@/views/pro-config/pro-setting/index.vue"
),
name: "ProSetting",
meta: {
title: `项目设置`,
icon: "redis",
},
},
{
path: "color-setting",
component: () =>
import(
/* webpackChunkName: 'colorSetting' */ "@/views/pro-config/color-setting/index.vue"
),
name: "ColorSetting",
meta: {
title: `颜色设置`,
icon: "color",
},
},
{
path: "fact-decomp",
component: () =>
import(
/* webpackChunkName: 'factDecomp' */ "@/views/pro-config/fact-decomp/index.vue"
),
name: "FactDecomp",
meta: {
title: `工厂分解`,
icon: "list",
},
},
],
},
/* === 项目空间路由 end === */
Vuex 实现切换数据
路由导航守卫:每次默认进入系统空间,若去往的路由地址的 menuTitle
是项目空间,则进入项目空间。
路由导航守卫
router.beforeEach((to, from, next) => {
// 重置
store.commit("menuBar/setIndex", 0);
let f1 = to.matched[0] && to.matched[0].meta.menuTitle;
if (f1) {
// 进入项目空间
store.commit("menuBar/setIndex", 1);
next();
} else {
next();
}
});
Vuex 代码
src/store/modules/menuBar.js
const state = {
// 默认为第一列:系统空间 0
menuBarIndex: JSON.parse(window.localStorage.getItem("menuBarIndex") || 0),
// 项目空间的 id
menuProjectId: JSON.parse(window.localStorage.getItem("menuProjectId" || 0)),
// 项目空间的 名称
menuProjectName: window.localStorage.getItem("menuProjectName" || ""),
};
const mutations = {
setIndex(state, payload) {
state.menuBarIndex = JSON.parse(payload);
window.localStorage.setItem("menuBarIndex", payload);
},
setProjectId(state, payload) {
state.menuProjectId = JSON.parse(payload);
window.localStorage.setItem("menuProjectId", payload);
},
setProjectName(state, payload) {
state.menuProjectName = payload;
window.localStorage.setItem("menuProjectName", payload);
},
};
const getters = {};
const actions = {};
export default {
namespaced: true,
state,
mutations,
getters,
actions,
};
src/store/getters.js
const getters = {
// ……其他代码
menuBarIndex: (state) => state.menuBar.menuBarIndex,
menuProjectId: (state) => state.menuBar.menuProjectId,
menuProjectName: (state) => state.menuBar.menuProjectName,
};
export default getters;
src/store/index.js
import Vue from "vue";
import Vuex from "vuex";
import getters from "./getters";
import menuBar from "./modules/menuBar";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
menuBar,
},
getters,
});
export default store;
本文来自博客园,作者:shayloyuki,转载请注明原文链接:https://www.cnblogs.com/shayloyuki/p/17442891.html
posted on 2023-05-30 13:09 shayloyuki 阅读(3715) 评论(0) 编辑 收藏 举报