需求:点击顶部导航栏的不同栏位实现左侧导航栏菜单的不同展示实现联动效果。
点击顶部导航栏按钮将对应的左侧导航栏数据传递给vuex,并在左侧导航栏父组件中接收并传递给左侧导航栏子组件,使用递归组件实现渲染等,具体的优化可以看下面的注释即可。
//顶部导航栏组件
<template>
<div
style="
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
"
>
<div class="top_div1">
<img
src="../assets/logo.png"
alt="log"
style="width: 50px; height: 60px"
/>
<div style="width: 100px">后台管理系统</div>
</div>
<div style="width: 450px; box-sizing: border-box">
<el-menu
:default-active="activeIndex2"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
class="top_div2"
>
<el-menu-item
:index="String(index)"
v-for="(item, index) in lists"
:key="index"
>{{ item.name }}</el-menu-item
>
<el-submenu index="4">
<template slot="title">我的工作台</template>
<el-menu-item index="4-1">设置</el-menu-item>
<el-menu-item index="4-2">退出</el-menu-item>
</el-submenu>
</el-menu>
</div>
</div>
</template>
<script>
import { mapMutations } from "vuex";
export default {
name: "showTop",
data() {
return {
num: 0,
//导航栏高亮
activeIndex2: null,
// 假设这是请求回来的数据
lists: [
{
name: "首页",
id: 0,
leftMenus: [
{
id: 1,
title: "用户管理",
key: "/user",
name: "user",
rights: ["view", "edit", "add", "delete"],
},
{
id: 2,
title: "商品管理",
key: "/products",
name: "products",
children: [
{
id: 21,
title: "品类管理",
key: "/categroy",
name: "categroy",
rights: ["view", "edit", "add", "delete"],
},
{
id: 22,
title: "商品生产",
key: "/product",
name: "product",
rights: ["view", "edit", "add", "delete"],
},
],
},
{
id: 3,
title: "角色管理",
key: "/sex",
name: "sex",
rights: ["view", "edit", "add", "delete"],
},
],
},
{
name: "商品",
id: 1,
leftMenus: [
{
id: 1,
title: "用户管理2",
key: "/user2",
name: "user2",
rights: ["view", "edit", "add", "delete"],
},
],
},
{
name: "订单",
id: 2,
},
{
name: "会员",
id: 3,
},
{
name: "设置",
id: 4,
},
],
};
},
mounted() {
// 调整高亮设置,实现刷新不复原
if (localStorage.getItem("activeIndex2")) {
this.activeIndex2 = localStorage.getItem("activeIndex2");
} else {
this.activeIndex2 = String(this.lists[0].id);
}
//用来默认展示左侧导航栏
let num = localStorage.getItem('key')
if(num){
this.setLeftMenus(this.lists[num].leftMenus);
}else{
this.setLeftMenus(this.lists[0].leftMenus);
}
},
methods: {
...mapMutations(["setLeftMenus"]),
// 顶部导航栏点击事件
handleSelect(key, keyPath) {
console.log(key, keyPath);
// 解决element ui组件库中顶部导航栏刷新高亮复原问题,也可存储在vuex中
if (key != "4-2") {
localStorage.setItem("activeIndex2", String(this.lists[key].id));
// console.log("aaa",this.lists[key].leftMenus)
if (this.lists[key].leftMenus) {
// 拿到所点击的导航栏的leftMenus,并存储在vuex中,然后在AsideLeft中拿到该数据
this.setLeftMenus(this.lists[key].leftMenus);
//点击顶部导航栏跳转到对应的左侧导航栏的第一个路由上
this.$router.push({ name: this.lists[key].leftMenus[0].name });
//实现点击首页回到welcome页面
if(key == 0){
this.$router.push({ name: "welcome" });
}
// 将key存储用来控制刷新左侧导航栏展示问题
localStorage.setItem('key',key)
}
}
// 判断是否是退出按钮
if (key == "4-2") {
// 清空本地缓存的token
localStorage.removeItem("token");
// 清除所有本地缓存
localStorage.clear()
// 跳转至登录页
this.$router.push({ name: "login" });
}
},
},
};
</script>
<style>
.top_div1 {
height: 60px;
display: flex;
flex-direction: row;
}
.top_div2 {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
</style>
//vuex
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
export default new Vuex.Store({
state:{
activeIndex:'',
leftMenus:null
},
mutations:{
setActiveIndex2(state,e){
state.activeIndex = e
window.localStorage.setItem('activeIndex2',e)
},
setLeftMenus(state,e){
state.leftMenus=e
window.localStorage.setItem('leftMenus',JSON.stringify(e))
}
},
getter:{
newActiveIndex:state=>{
return state.activeIndex
}
}
})
//左侧导航栏父组件
<template>
<div>
<!-- 动态设置default-active为当前活跃路由的path可实现刷新多级菜单折叠问题 -->
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo"
background-color="rgb(60, 60, 60)"
text-color="#fff"
active-text-color="#ffd04b"
router
>
<Aside_demo :leftMenus="leftMenus"></Aside_demo>
</el-menu>
</div>
</template>
<script>
import Aside_demo from "../components/Aside_demo.vue";
import { mapState } from "vuex";
export default {
name: "AsideLeft",
data() {
return {};
},
computed: {
...mapState(["leftMenus"]),
},
components: {
Aside_demo,
},
methods: {},
};
</script>
<style>
.el-menu {
width: 200px;
}
</style>
//左侧导航栏子组件
<template>
<div>
<div v-for="(item, index) in leftMenus" :key="index">
<!-- 多级导航 -->
<!-- 这里设置动态key值,解决高亮问题,也可实现路由跳转 ,并通过设置v-if来判断数据有无二级菜单数据,以此来展示二级菜单-->
<el-submenu :index="item.key" v-if="item.children">
<template slot="title">
<i class="el-icon-location"></i>
<span>{{ item.title }}</span>
</template>
<!-- 这里使用递归组件,用来遍历多级菜单,将children数据传给递归组件,自己遍历自己 -->
<nav-menu :leftMenus="item.children"></nav-menu>
</el-submenu>
<!-- 一级导航 -->
<!-- 通过判断当前活跃的路由path是否等于对应的左侧导航栏的key来实现默认第一个高亮以及处理一刷新高亮复原问题 -->
<el-menu-item :index="item.key" v-else :style="$route.path==item.key?'color:#ffd04b':''">
<i class="el-icon-menu"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</div>
</div>
</template>
<script>
export default {
// 注意使用递归组件,name值就要改变了
name: "NavMenu",
data() {
return {};
},
props:['leftMenus'],
methods: {},
};
</script>
<style></style>