**效果**
![在这里插入图片描述](https://img-blog.csdnimg.cn/0b971d35afdb4021894e3246b16ce969.png#pic_center)
**清除标签默认样式样式**
APP.vue文件
**效果**
![在这里插入图片描述](https://img-blog.csdnimg.cn/47c54346719e4a80b5c48e5d6ea66661.png#pic_center)
##### 4.5、菜单点击跳转功能实现
我们上面已经完成了左侧的样式以及基本的布局,现在我们要完善一下当我们点击菜单选项,完成路由跳转展示
###### 4.5.1、根据菜单数据,我们先定义一下我们未定义的路由\*\*
**先新建对应路由页面文件**
**Mall.vue商品管理页面**
Mall页面
}
}
}
**qtPageOne.vue其他页面1页面**
qtPageOne页面
}
}
}
**qtPageTow.vue其他页面2页面**
qtPageTow页面
}
}
}
**router文件夹index.js路由·配置文件**
// 路由配置文件
// 如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能,也可以再main.js引入
import Vue from “vue”;
import VueRouter from “vue-router”;
Vue.use(VueRouter);
import Main from “…/views/Mian.vue”;
// 主页面
// 1.创建路由组件,也就是我们创建views里面的组件文件
// 引入我们创建的vue组件文件
import Home from “…/views/Home.vue”;
import User from “…/views/User.vue”;
import Mall from “…/views/Mall.vue”;
import qtPageOne from “…/views/qtPageOne.vue”;
import qtPageTow from “…/views/qtPageTow.vue”;
// 2. 定义路由
// 将路由与组件进行映射
const routes = [
// 主页面
{
path: “/”,
// /默认是主出口主页面组件
redirect:‘home’,
// 重定向到home
component: Main,
children: [
// 子路由
{ path: “home”, component: Home },
// 首页
{ path: “user”, component: User },
// 用户管理
{ path: “mall”, component: Mall },
// 商品管理
{ path: “page1”, component: qtPageOne },
// 其他页面1
{ path: “page2”, component: qtPageTow },
// 其他页面2
],
},
];
// 3. 创建 router 实例,然后传routes配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
routes, // (缩写) 相当于 routes: routes
});
// 导出我们的router实例
export default router;
文件结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/93d91eaccc2345bd9045e0cfac4c1c43.png#pic_center)
###### 4.5.2、点击菜单,根据点击菜单的数据跳转应路由页面\*\*
v-for=“item in menuHasChildren”
:key=“item.label”
:index=“item.label”
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{
{ item.label }}</span>
</template>
<!-- 遍历生成有二级菜单的子菜单 -->
<el-menu-item-group v-for="subItem in item.children" :key="subItem.path">
<!-- 子菜单渲染 -->
<!-- clickMenu跳转 -->
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path">{
{ subItem.label }}</el-menu-item>
</el-menu-item-group>
</el-submenu>
**效果**
![在这里插入图片描述](https://img-blog.csdnimg.cn/915cb823c3b6485a85f1191272d49fae.png#pic_center)
### 5、通用管理后台(header组件与样式搭建)
##### 5.1、封装header区域组件与样式
菜单区域我们已经完成了,接下来我们完成一下header区域的布局和样式编写,一个是左侧的按钮区域和面包屑区域,另外就是用户头像区域带下来菜单。
封装创建一个CommonHeader.vue
![在这里插入图片描述](https://img-blog.csdnimg.cn/aa0c96dbd9c6401683ae4c98383586a1.png#pic_center)
在Main.vue中引入并且使用
Main.vue
<!-- router-view Main下面子路由的路由出口 -->
<router-view>
</router-view>
</el-main>
</el-container>
</el-container>
}
}
}
**效果**
![在这里插入图片描述](https://img-blog.csdnimg.cn/1142ccc553914e52ac94bf5ce411f1a9.png#pic_center)
##### 5.2、通过vuex实现左侧折叠
前面已经完善了header区域的布局和样式,接下来把header区域按钮的点击操作菜单折叠与展开完善一下!但是按钮在CommonHeader.vue组件中,那么如何去操作CommonAside.vue菜单组件呢?
![在这里插入图片描述](https://img-blog.csdnimg.cn/42dff2cbb51c4a7c924011df761e8e5c.png#pic_center)
因为状态修改牵扯到俩个组件中的变化,接下来我们就用vuex去实现
###### 5.2.1、什么是vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex分为俩个比较大的版本,一个是4.0(主要针对于vue3),一个3.0(主要针对vue2),
[Vuex4官网](https://bbs.csdn.net/topics/618166371)
[Vuex3官网](https://bbs.csdn.net/topics/618166371)
![在这里插入图片描述](https://img-blog.csdnimg.cn/32ad82dde5954c7097055e921aac5aee.png#pic_center)
###### 5.2.2、安装vuex
npm i [email protected]
![在这里插入图片描述](https://img-blog.csdnimg.cn/b58ab925778249759c8385f52d901c18.png#pic_center)
###### 5.2.3、配置vuex
在src文件下创建一个store文件夹,在store新建一个index.js文件配置vuex
因为菜单和用户是俩部分单独的一块信息,对于这种数据,按照模块化的思想,把它拆分成俩个 modules
新建一个tab.js用于管理菜单的数据
// 管理菜单的数据
export default{
state:{
isCollapse:false,
// isCollapse用于控制菜单的展开和收起
},
mutations:{
// 修改菜单展开收起方法
collapseMenu(state){
state.isCollapse=!state.isCollapse
}
}
}
``
在store下面的index.js配置vuex和注入`
// 引入vue
import Vue from 'vue'
import Vuex from 'vuex'
import tab from './tab'
// 引入管理菜单的数据
Vue.use(Vuex)
// 将Vuex全局注入
// 创建vuex实例
export default new Vuex.Store({
modules:{
tab
}
})
在mian.js将我们的vuex实例挂载到vue上
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 引入element-ui样式文件
import router from './router'
// 引入路由文件
import store from'./store'
Vue.config.productionTip = false
Vue.use(ElementUI);
// 全局注入element-ui
new Vue({
router,
// 挂载router实例
store,
// 挂载vuex实例
el: '#app',
render: h => h(App),
}).$mount('#app')
5.2.4、使用vuex
在我们组件中使用vuex完成我们的点击按钮让菜单展开收起的功能
在CommonHeader.vue中点击按钮调用mutations方法修改vuex中state里isCollapse数据
CommonHeader.vue
HandelMenu方法使我们点击按钮事件方法
<template>
<div class="header-content">
<!-- 头部组件 -->
<div class="l-content">
<!-- 左侧 -->
<!-- icon的按钮 ,HandelMenu点击按钮方法 -->
<el-button @click="HandelMenu" icon="el-icon-menu" size="mini"></el-button>
<!-- 面包屑,先用span标签代替 -->
<span class="text">首页</span>
</div>
<div class="r-content">
<!-- 右侧 -->
<!-- el-dropdown 下拉菜单-->
<el-dropdown>
<img class="user" src="/image/Li4vYXNzZXRzL3R4LnBuZw%3D%3D" alt="">
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
export default {
data() {
return {};
},
methods:{
HandelMenu(){
// 按钮点击事件,调用vuex的mutations方法
this.$store.commit('collapseMenu')
}
}
};
</script>
<style lang="less" scoped>
.header-content {
padding: 0 20px;
background-color: #333;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
.text {
color: white;
font-size: 14px;
margin-left: 10px;
}
.r-content{
.user{
// 头像
width: 40px;
height: 40px;
border-radius: 50%;
}
}
}
</style>
CommonAside.vue
获取vuex的state中的isCollapse数据,绑定我们菜单实现菜单展开和收缩
在computed属性中进行使用的
<template>
<el-menu
default-active="1-4-1"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
:collapse="isCollapse"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
>
<h3>vue前端通用管理后台</h3>
<!-- 点击菜单选项触发clickMenu事件 -->
<el-menu-item
@click="clickMenu(item)"
v-for="item in menuNoChildren"
:key="item.name"
:index="item.name"
>
<!-- 遍历生成无子菜单数据 -->
<i :class="`el-icon-${item.icon}`"></i>
<!-- i标签是渲染的element-ui的图标,使用了es6中的自符模板 -->
<span slot="title">{
{ item.label }}</span>
<!-- span 标签是菜单名字 -->
</el-menu-item>
<!-- 遍历生成有二级菜单的一级菜单菜单 -->
<el-submenu
v-for="item in menuHasChildren"
:key="item.label"
:index="item.label"
>
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{
{ item.label }}</span>
</template>
<!-- 遍历生成有二级菜单的子菜单 -->
<el-menu-item-group v-for="subItem in item.children" :key="subItem.path">
<!-- 子菜单渲染 -->
<!-- clickMenu跳转 -->
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path">{
{ subItem.label }}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<style scoped lang="less">
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
// 菜单高度和标题样式
.el-menu {
height: 100vh;
border-right: none;
h3 {
margin: 0;
color: white;
text-align: center;
line-height: 48px;
font-size: 16px;
font-weight: 400;
}
}
</style>
<script>
export default {
data() {
return {
// menuData 菜单数据
menuData: [
{
path: "/",
name: "home",
label: "首页",
icon: "s-home",
url: "Home/Home",
},
{
path: "/mall",
name: "mall",
label: "商品管理",
icon: "video-play",
url: "MallManage/MallManage",
},
{
path: "/user",
name: "user",
label: "用户管理",
icon: "user",
url: "UserManage/UserManage",
},
{
label: "其他",
icon: "location",
children: [
{
path: "/page1",
name: "page1",
label: "页面1",
icon: "setting",
url: "Other/PageOne",
},
{
path: "/page2",
name: "page2",
label: "页面2",
icon: "setting",
url: "Other/PageTwo",
},
],
},
],
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
// 点击菜单,跳转
clickMenu(item) {
// item 触发传递的数据
console.log(item.path);
// 添加容错逻辑
// 当我们的路由与我们跳转的路由不一致时,才允许跳转
// 当前页面路由
if(this.$route.path!=i