首先加一下菜单的两个属性
json
:unique-opened="true" // 是否只保持一个子菜单的展开
:router="true" // 是否启用 vue-router 模式。 启用该模式会在激活导航时以 index 作为 path 进行路由跳转 使用 default-active 来设置加载时的激活项。
html
<template>
<div class="home-container">
<div class="home-header">头部</div>
<div class="home-menu">
<el-menu
active-text-color="#ffd04b"
background-color="#545c64"
class="el-menu-vertical-demo"
default-active="2"
text-color="#fff"
:unique-opened="true"
:router="true"
>
<el-sub-menu v-for="menu in newMenus" :index="menu.id">
<template #title>
<span>{{ menu.title }}</span>
</template>
<template v-for="submenu in menu.children">
<el-menu-item v-if="submenu.hidden === 0" :index="submenu.id">{{ submenu.title }}</el-menu-item>
</template>
</el-sub-menu>
</el-menu>
</div>
<div class="home-content">右侧内容</div>
</div>
</template>
<script lang='ts' setup>
/**
{
id: {
title: "一级菜单",
children: [
{title: "二级菜单"},
{title: "二级菜单"},
{title: "二级菜单"},
{title: "二级菜单"},
]
}
}
* */
import { } from 'vue'
import { useStore } from 'vuex'
interface MenuObj {
id: string
title: string
parentId: string
hidden: 0 | 1
children?: MenuObj[]
}
interface NewMenus {
[key: string]: MenuObj
}
const store = useStore();
const newMenus: NewMenus = store.getters.getNewMenus;
console.log('newMenus---------home-----------', newMenus)
</script>
<style lang='less' scoped>
.home-container {
position: relative;
height: 100%;
.home-header {
height: 70px;
background-color: goldenrod;
}
.home-menu {
position: absolute;
top: 70px;
left: 0;
bottom: 0;
width: 250px;
background-color: #a37676;
}
.home-content {
position: absolute;
top: 70px;
right: 0;
left: 250px;
bottom: 0;
background-color: skyblue;
}
}
</style>
然后等价路由导航守卫
vuex 添加默认导出
ts
import { createStore } from 'vuex'
import { type App } from 'vue'
interface MenuObj {
id: string
parentId: string
children?: MenuObj[]
}
interface State {
menus: MenuObj[]
}
interface NewMenus {
[key: string]: Partial<MenuObj>
}
const store = createStore<State>({
state() {
return {
menus: []
}
},
getters: {
getNewMenus(state) {
const newMenus: NewMenus = {}
const menus = state.menus
for (let i = 0; i < menus.length; i++) {
const menu = menus[i] as MenuObj
if (menu.parentId === '0') {
// 一级菜单:初始化 children 为空数组,方便后续 push
newMenus[menu.id] = {
...menus[i],
children: newMenus[menu.id]?.children || []
}
} else {
// 子级菜单:根据 parentId 找到对应的父级
const parentId = menu.parentId
newMenus[parentId] = newMenus[parentId] || {}
newMenus[parentId].children = newMenus[parentId].children || []
newMenus[parentId].children.push(menu)
}
}
console.log('newMenus--------------------', newMenus)
return newMenus;
}
},
mutations: {
updateMenus(state, menus) {
console.log('updateMenus--->', state, menus)
state.menus = menus
}
},
actions: {},
modules: {}
})
export const initStore = (app: App<Element>) => {
app.use(store)
}
export default store
路由添加守卫
ts
import {
createRouter,
createWebHashHistory,
type RouteRecordRaw
} from 'vue-router'
import { type App } from 'vue'
import store from '../store'
import Cookie from 'js-cookie'
const routes: RouteRecordRaw[] = [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: () => import('../views/login/login.vue')
},
{
path: '/home',
name: 'home',
component: () => import('../views/home/home.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes // 路由配置
})
// 前置导航守卫
router.beforeEach((to, from, next) => {
// 1、token && vuex里面的 menus 为空
const token = Cookie.get('token')
console.log(store)
if(token && store.state.menus.length === 0) {
console.log('menus为空')
}
})
export const initRouter = (app: App<Element>) => {
app.use(router)
}