有一个菜单树,顶层菜单下面有多个子菜单,子菜单下还有子菜单。。。

这时候就要用递归处理

1 定义多级菜单

修改 src/router/index.js 的 / 路由

  {
path: '/',
redirect: '/dashboard',
name: 'Container',
component: Container,
children: [
{path: 'dashboard', name: '首页', component: Dashboard,
children: [
{path: 'dashboard1', name: '首页1', component: Dashboard,},
{path: 'dashboard2', name: '首页2', component: Dashboard,
children: [
{path: 'dashboard21', name: '首页21', component: Dashboard,},
{path: 'dashboard22', name: '首页22', component: Dashboard, },
] },
]
},
{path: 'article', name: '文章', component: Article, },
]
}

2 抽出Sidebar组件

生成的递归路由放在侧边栏,因此抽取 sidebar 组件,sidebar 包含logo和 递归路由

再抽取 SidebarItem 为单独的路由组件,方便递归调用

2.1 Sidebar

Sidebar 接收collapse、路由数组,同时引入 SidebarItem 组件

子组件传入:

  • barIdx: 当前路由的索引,用来定位子菜单
  • subroute: 路由对象
  • fatherpath: 父路径,如 /、 /a/b
<template>
<div>
<div class="app-side-logo">
<img src="@/assets/logo.png"
:width="collapse ? '60' : '60'"
height="60" />
</div> <el-menu class="el-menu-vertical-demo"
:default-active="defaultActive"
router
:collapse="collapse"
>
<SidebarItem v-for="(item, idx) in routes"
:subroute="item"
:fatherpath="fatherPath"
:barIdx="idx" :key="idx" />
</el-menu>
</div>
</template> <script>
import SidebarItem from './SidebarItem'
export default {
naem: "Sidebar",
components: {
SidebarItem
},
props: {
collapse: {
type: Boolean
},
routes: {
type: Array
}
},
computed: {
// 首次进入页面时展开当前页面所属的菜单
defaultActive(){
return this.$route.path
},
fatherPath(){
// 这里直接获取路由配置的 '/' 项
return this.$router.options.routes[1].path
}
}
}
</script> <style> </style>

2.2 SidebarItem

SidebarItem 接收路由、父路由path、父级idx,然后递归调用自身

<template>
<!-- 如果当前 subroute 有子节点 -->
<el-submenu v-if="!subroute.hidden && subroute.children && subroute.children.length > 0"
:index="genPath(fatherpath, subroute.path)">
<!-- 创建菜单分组 -->
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">{{subroute.name}}</span>
</template> <!-- 递归调用自身,直到 subroute 不含子节点 -->
<SidebarItem v-for="(submenu, subidx) in subroute.children"
:subroute="submenu"
:fatherpath="genPath(fatherpath, subroute.path)"
:barIdx="subidx"
:key="barIdx + '-' + subidx"
/>
</el-submenu> <!-- 当前节点不含子节点且非隐藏 -->
<el-menu-item style="font-weight: 400"
v-else-if="!subroute.hidden"
:index="genPath(fatherpath, subroute.path)"
>{{subroute.name}}
</el-menu-item> <el-menu-item style="font-weight: 400"
v-else
:index="genPath(fatherpath, subroute.path)"
>{{ subroute.name }}
</el-menu-item>
</template> <script>
export default {
name: 'SidebarItem',
props: {
subroute: {
type: Object
},
barIdx: {
type: [String, Number]
},
fatherpath: {
type: String
}
},
computed: {
// 默认激活的路由, 用来激活菜单选中状态
defaultActive: function(){
return this.$route.path
},
},
methods: {
// 生成侧边栏路由,格式: /a/b/c
genPath: function(){
let arr = [ ...arguments ]
let path = arr.map(v => {
while (v[0] === '/'){
v = v.substring(1)
}
while(v[-1] === '/'){
v = v.substring(0, v.length)
}
return v
}).join('/')
path = path[0] === '/' ? path : '/'+path
return path
},
handleOpen: function(key, keyPath) {
console.log(key, keyPath)
},
handleClose: function(key, keyPath) {
console.log(key, keyPath)
}
},
mounted: function(){
console.log('sidebar routes: ', this.routes)
}
}
</script> <style>
</style>

3 项目结构

此时 src 的目录结构

│  App.vue
│ main.js
├─assets
│ logo.png
├─components
│ HelloWorld.vue
│ Sidebar.vue
│ SidebarItem.vue
├─container
│ Container.vue
├─router
│ index.js
├─styles
│ index.scss
└─views
│ TheLogin.vue
├─article
│ index.vue
└─dashboard
index.vue

4 修改容器配置

src/container/Container.vue 引入 Sidebar 组件

<template>
<!-- ... -->
<el-aside class="app-side app-side-left"
:class="isCollapse ? 'app-side-collapsed' : 'app-side-expanded'">
<Sidebar :collapse="isCollapse" :routes="$router.options.routes[1].children"/>
</el-aside>
<!-- ... -->
</template>
<script>
import Sidebar from '@/components/Sidebar'
export default {
name: 'Container',
components: {
Sidebar
},
/** ... */
</script>

页面效果



vue+elementui搭建后台管理界面(5递归生成侧栏路由)的更多相关文章

  1. vue+elementui搭建后台管理界面(7 vuex和mockjs的使用)

    将权限管理应用到系统,首先做好登录, 点击登录按钮后,触发以下动作 vuex 中的 login 动作,设置 cookie vuex 中的 getuserinfo , 获取权限.用户名.头像等 由于目前 ...

  2. vue+elementui搭建后台管理界面(2首页)

    1 会话存储 使用html5的 sessionStorage 对象临时保存会话 // 保存会话 sessionStorage.setItem('user', username) // 删除会话 ses ...

  3. vue+elementui搭建后台管理界面

    1 会话存储 使用html5的 sessionStorage 对象临时保存会话 // 保存会话 sessionStorage.setItem('user', username) // 删除会话 ses ...

  4. vue+elementui搭建后台管理界面(1登录)

    1 node环境安装 从 node官网下载安装包 2 vue-cli npm install vue-cli -g 3 新建项目 vue init webpack vue-project 可保持默认, ...

  5. vue+elementui搭建后台管理界面(8 同步/异步获取数据渲染table)

    elementui已经封装好了 el-table 组件,只需要指定 data 数据源即可,因此通常在 vue 实例生命周期的 created 阶段,从数据库获取数据,再将返回的数据绑定到 data 如 ...

  6. vue+elementui搭建后台管理界面(6登录和菜单权限控制)

    不同的权限对应不同的路由(菜单),同时侧边栏也根据权限异步生成,实现登录和鉴权思路如下: 登录:点击登录,服务器验证通过后返回一个 token ,然后存到 cookie,再根据 token 拉取用户权 ...

  7. vue+elementui搭建后台管理界面(6登录和菜单权限控制[二])

    根据权限计算路由的代码 /** * 通过meta.role判断是否与当前用户权限匹配 * @param roles * @param route */ function hasRoles (roles ...

  8. vue+elementui搭建后台管理界面(3侧边栏菜单)

    上一节搭好了主框架,但是标签页和侧边栏只是分别展示了各自的菜单,如何将二者联动起来? 定义路由规则:当有 children 属性时,从 children 里取出 path 填充到侧边栏,如: { pa ...

  9. vue+elementui搭建后台管理界面(4使用font-awesome)

    使用font-awesome npm install --save font-awesome 修改 src/main.js 增加 import 'font-awesome/scss/font-awes ...

随机推荐

  1. python 3.7.4 安装 opencv

    明确一下,我们需要使用python来调用opencv中的库函数,所以需要安装opencv-python. 主要需要安装: 1. opencv-python 2. numpy 第一步先来安装opencv ...

  2. RabbitMQ topic 交换器

    topic交换器:"."将路由键分为几个标识符,"*"匹配一个, "#"可以匹配多个 1:路由键为*或者#的时候 *:只能匹配单个的字符串 ...

  3. 反射,内置方法,__str__ __repr__

    反射 反射用到的mmp模块 def wahaha():print('wahaha') class QQxing: def __init__(self,name): self.name = name d ...

  4. python3 queue队列

    一.queue队列 1.python3中的队列模块是queue,不是Queue 2.一般涉及到同步,多线程之类用到队列模块 3.定义了 queue.Queue 类,以及继承它的 queue.LifoQ ...

  5. k8s证书之etcd,api,front-proxy配置文件

    这几个文件,是要结合前面的master安装脚本的. 所以有的json文件中会出现一些LOCAL_HOSTS_L,THIS_HOST之类的变量. 如果手工单独使用这些文件,要将这些变量替换为合适的IP或 ...

  6. P2015 二叉苹果树[树形dp+背包]

    题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...

  7. test20190729 夏令营NOIP训练14

    40+100+0=140. 基因光线 黑大帅统治古古怪界后,一直在玩一种很奇葩的游戏.在一个二维平面上,他先复制了n个小A,把他们放在不同的位置,然后射出一条ax+by+c=0的基因光线,宽度为d,即 ...

  8. Spring Boot MyBatis 通用Mapper 自动生成代码

    一.在pom.xml文件中进入mybatis自动生成代码相关的jar包: 注意: <configurationFile>标签中配置的是“generatorConfig.xml”文件位置. ...

  9. Django --- 多对多关系创建,forms组件

    目录 多对多三种创建方式 1.系统直接创建 2.自己手动创建 3.自己定义加与系统创建 forms组件 1. 如何使用forms组件 2. 使用forms组件校验数据 3. 使用forms组件渲染标签 ...

  10. 依赖注入(DI)和控制反转(IOC)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...