Element ui 引入
全局引入
npm i element-ui -S
在main.js文件里
按需引入
安装 babel-plugin-component:
npm i element-ui -S
npm install babel-plugin-component -D
在main.js文件里
在babel.config.js文件里
嵌套路由
左侧菜单栏的样式
Container布局,左侧菜单栏commonAside组件
main.vue配置的是整体的样式,用的是Container布局容器里的组件
el-main这块是子路由的路由出口,el-aside这块是放左侧菜单栏的组件
commonAside菜单
导航菜单,因为后续会有折叠功能,所以用的是这个
导航菜单的话分为有子菜单的一部分,和没有子菜单的一部分,所以给menuData
里的数据(后续可能会改成接口)写了个计算方法,用到了es6的filter
,noChildren
就把menuData
里没有children的给过滤出来,所以是!item.children
,给item.children取反,hasChildren
就把有children的给过滤出来。
在组件里就用对应的方法来v-for遍历。
icon这里运用到了es6的模板字符串
- 模板字符串使用反引号 (``) 来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法(${expression})的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来
具体代码:
<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>通用后台管理系统</h3>
<!-- 没有子菜单,对noChildren进行遍历, item表示当前的每一项,key用于添加标记当前元素的唯一性,固定且不变的值.-->
<!-- index="2",element-ui里表示,也是唯一表示的意思 . 给它加个唯一标识,和key一样-->
<el-menu-item
v-for="item in noChildren"
:key="item.name"
:index="item.name"
>
<!-- i标签的class展示的是图标,图标根据menuData来展示,所以可以用es6的模板字符串来拼接渲染 -->
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{
{
item.label }}</span>
</el-menu-item>
<!--有子菜单,对hasChildren进行遍历,这里为什么用label呢,因为在"其他"数据里没有name,所以用label -->
<el-submenu
v-for="item in hasChildren"
:key="item.label"
:index="item.label"
>
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{
{
item.label }}</span>
</template>
<!-- 有子菜单的children ,对item.children进行遍历 -->
<el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
<el-menu-item :index="subItem.name">{
{
subItem.label }}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
.el-menu{
height: 100vh;
h3{
color: white;
text-align: center;
line-height: 48px;
font-size: 16px;
font-weight: 400;
}
}
</style>
<script>
export default {
name: "commonAside",
data() {
return {
isCollapse: false,
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);
},
},
//计算属性,过滤数据,一种没有子菜单,一种有子菜单
computed: {
//没有子菜单
noChildren() {
//filter:接收一个函数作为参数,对menuData进行遍历,item会拿到其中的某一项,来根据true或false来判断当前的数据是否返回.
return this.menuData.filter((item) => !item.children);
},
//有子菜单
hasChildren() {
return this.menuData.filter((item) => item.children);
},
},
};
</script>
菜单跳转功能
根据menuData
里的path,在路由文件里配置路由
在commonAside组件里,写上click
事件,当点击菜单的时候,跳转到对应的页面
重复跳转报错问题解决
//点击菜单 根据menuData里的path来跳转,所以要传入一个参数
clickMenu(item){
//判断页面的路由与跳转的路由是否一致,不一致才允许跳转
if(this.$route.path != item.path && !(this.$route.path === '/home' && (item.path === '/'))){
this.$router.push(item.path)
}
// this.$router.push(item.path)
}
菜单折叠效果(vuex)
先新建一个commonHeader组件,在mainHome.vue里引入
Header区域左侧菜单折叠效果
点击commonHeader组件的按钮,要实现左侧commonAside组件的变化。
vuex:
- 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用与任意组件通信
- 什么时候使用:
1.多个组件依赖于同一状态
2.来自不同组件的行为需要变更同一状态
vue2中,要用vuex的3版本
vue3中,要用vuex的4版本
npm install vuex@3.6.2 --save
为什么不在main.js里引入vuex而是在store的index.js里引入vuex?
在main.js里引入vuex会报错:必须在创建store之前调用Vue.use(Vuex)
这是因为import
命令具有提升效果,会提升到整个模块的头部,首先执行
具体代码
main.js
store的index.js
tab.js
commonHeader.vue里就要用到点击事件,点击的时候调用mutations里的collapseMenu方法
当state发生变化的时候,在commonAside.vue里获取到store中的state
优化
在折叠菜单的时候,对标题,可以做一个三元判断,根据isCollapse,折叠了就显示后台,没有折叠就显示通用后台管理系统
菜单折叠的时候头部组件没有跟着移动是因为在main.js里引入ui库的container组件的时候,给它定义了宽度,只要改成auto就可以了
首页
首页整体分为左右两侧
box-card