对树形菜单的递归操作,首先应该对树形菜单数据进行整理,优化成自己需要的类型

比如Vue + ElementUI的动态侧边栏数据

 export function routerRoleToPretty (routing = [], deepPath = '/main/') {
return routing.map(item => {
if (item instanceof Array) { // 由于后台返回数据问题 所以这里给了一个兼容判断
return item[0]
} else {
return item
}
}).map(item => {
return {
id: item.id,
path: item.path,
name: item.name, // 也可通过name方式跳转
fullPath: `${deepPath + item.path}`, // 这里我们获取到VueRouter的绝对路由 通过path的方式去进行跳转页面
meta: { // meta 中参数用来确定显示问题
icon: item.icon,
childrenLength: item.ziJi_1 ? item.ziJi_1.length : 0,
enTitle: item.enTitle,
zhTitle: item.zhTitle,
desc: item.description,
type: item.type,
parentId: item.parentId
},
children: routerRoleToPretty(item.ziJi_1 ? item.ziJi_1 : [], deepPath + item.path + '/')
}
})
}

由于后台返回的数据格式是 [[{}], [{}]]格式所以第一次需要将数据暴露出

这样一个递归就完成了数据处理

当然如果你想将递归数据全部取出来EcmaScript提供了一个方法 Array.prototype.flat()

var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

当参数为 Infinity 时不限制递归数据深度 这样就可以获取到所有队规的对象 然后再去 map() 操作就很简单啦

var arr3 = [1, 2, [3, 4, [5, 6]]];
// 使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]

最后贴上ElementUI如何使用递归数据

父级组件

 <!-- 左侧菜单导航栏组件 -->
<template>
<scroll-bar>
<slot></slot>
<div class="app-nav-wrap">
<el-menu mode="vertical"
popper-class="roleMenuClass"
:default-active="routerAction"
:class="{'menu-nav': true, 'isCollapse': isCollapse}"
:unique-opened="true"
@open="handleOpen"
@close="handleClose"
:collapse="isCollapse"
background-color="#0A70F8"
text-color="#fff"
router>
<rm-menu :childrenData="routerMenu"></rm-menu>
</el-menu>
</div>
</scroll-bar>
</template> <script>
import { mapGetters, mapActions } from 'vuex'
import SystemConfigModule from '@/utils/api/System'
import RmMenu from './RecursiveMenu'
import ScrollBar from '@/components/common/ScrollBar'
// import { getHistoryRouter } from '@/utils/cookie'
export default {
components: { RmMenu, ScrollBar },
data () {
return {
routerMenu: [],
routerAction: this.$route.path
}
},
watch: {
'$route' (to) {
this.routerAction = to.path
}
},
created () {
this.rulesChange()
},
computed: {
...mapGetters([
'sliderbar'
]),
options () {
return this.$store.state.options
},
isCollapse () {
return this.sliderbar
}
},
methods: {
...mapActions({
UpdateRouterRole: 'UpdateRouterRole'
}),
handleOpen (key, keyPath) {
// console.log(key, keyPath)
},
handleClose (key, keyPath) {
// console.log(key, keyPath)
},
async rulesChange () {
this.routerMenu = await this.UpdateRouterRole(SystemConfigModule.SystemModule.MenuRole)
// console.log(this.routerMenu)
}
}
}
</script>
<style lang="scss" scoped>
@import '@/assets/sass/theme.sass';
/deep/ .app-nav-wrap {
.menu-nav:not(.el-menu--collapse) {
width: 200px;
// min-height: 400px;
min-width: 36px;
.menulist {
background-color: $menuBg !important;
transition: all .5s linear;
// 展开样式
.el-submenu.is-opened {
.el-menu.el-menu--inline {
.el-menu-item {
background-color: $subMenuBg !important;
transition: all .5s linear;
&.is-active {
background-color: $menuHover !important;
transition: all .5s linear;
}
}
}
}
// 样式
li.el-menu-item,.el-submenu__title {
&:hover {
background-color: $menuHover;
transition: all .5s linear;
}
}
// 高亮
a.router-link-active li.el-menu-item.is-active,
.el-menu-item.is-active{
background-color: $menuHover !important;
transition: all .5s linear;
}
.el-submenu__title,
.el-menu-item {
color: $fontColor;
transition: all .5s linear;
}
.el-submenu__icon-arrow.el-icon-arrow-down {
color: $fontColor;
}
}
}
// 小的菜单栏数据
.isCollapse{
width: 36px;
.menulist{
background-color: $menuBg !important;
transition: all .5s linear;
.el-submenu .el-submenu__title{
padding: 0 !important;
span{
display: none;
}
.icon-menu{
margin: 0;
font-size: 16px;
padding: 15px 8px;
}
i.el-submenu__icon-arrow{
display: none;
color: $fontColor;
}
}
// 样式
li.el-menu-item{
padding: 0 !important;
span{
display: none;
}
.icon-menu{
margin: 0;
font-size: 16px;
padding: 15px 8px;
}
}
// hover样式
li.el-menu-item,.el-submenu__title {
&:hover {
background-color: $menuHover;
transition: all .5s linear;
}
}
// 高亮
li.el-menu-item.is-active,
li.el-submenu.is-active {
background-color: $menuHover !important;
transition: all .5s linear;
// 更改默认继承
.el-submenu__title {
background-color: inherit !important;
}
}
}
}
.menulist a.router-link-exact-active.router-link-active li.el-menu-item.is-active{
background-color: $menuHover !important;
transition: all .5s linear;
}
i.icon-menu {
color: #fff;
}
}
</style>
<style lang="scss">
@import '@/assets/sass/theme.sass';
.roleMenuClass {
.menulist {
background-color: $menuBg !important;
transition: all .5s linear;
// 展开样式
.el-submenu.is-opened {
.el-menu.el-menu--inline {
.el-menu-item {
background-color: $subMenuBg !important;
transition: all .5s linear;
&.is-active {
background-color: $menuHover !important;
transition: all .5s linear;
}
}
}
}
li.el-menu-item,.el-submenu__title {
&:hover {
background-color: $menuHover;
transition: all .5s linear;
}
}
a.router-link-active li.el-menu-item.is-active,
.el-menu-item.is-active{
background-color: $menuHover !important;
transition: all .5s linear;
}
.el-submenu__title,
.el-menu-item {
color: $fontColor;
transition: all .5s linear;
}
.el-submenu__icon-arrow.el-icon-arrow-down {
color: $fontColor;
}
}
/deep/ .menulist a.router-link-exact-active.router-link-active li.el-menu-item.is-active{
background-color: $menuHover !important;
transition: all .5s linear;
}
i.icon-menu {
color: #fff;
}
}
</style>

子组件 RecursiveMenu.vue

 <template>
<section class="menulist">
<section v-for="item in childrenData" :key="item.id">
<!-- 没有子集的 -->
<el-menu-item :index="item.fullPath" v-if="item.meta.childrenLength === 0">
<i :class="['icon-menu', 'iconfont', item.meta.icon]"></i>
<span>{{langChange() ? item.meta.zhTitle : item.meta.enTitle}}</span>
</el-menu-item>
<!-- 子集只有一个的 只展示子集 -->
<el-menu-item :index="item.children[0].fullPath" v-if="item.meta.childrenLength === 1">
<i :class="['icon-menu', 'iconfont', item.meta.icon]"></i>
<span>{{langChange() ? item.children[0].meta.zhTitle : item.children[0].meta.enTitle}}</span>
</el-menu-item>
<!-- 子集大于一个的 -->
<el-submenu :popper-append-to-body="true" popper-class="roleMenuClass" v-if="item.meta.childrenLength > 1" :index="item.fullPath">
<template slot="title">
<i :class="['icon-menu', 'iconfont', item.meta.icon]"></i>
<span v-if="item.meta && item.meta.zhTitle && item.meta.enTitle">{{langChange() ? item.meta.zhTitle : item.meta.enTitle}}</span>
</template>
<rm-menu :childrenData="item.children"></rm-menu>
</el-submenu>
</section>
</section>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'RmMenu',
data () {
return {}
},
computed: {
...mapGetters([
'lang'
])
},
props: {
childrenData: {
default: () => [],
type: Array
}
},
methods: {
langChange () {
if (this.lang === 'zh') {
return true
} else {
return false
}
}
}
}
</script>

至此结束

递归函数 Vue ElementUI的更多相关文章

  1. spring boot + vue + element-ui全栈开发入门——开篇

    最近经常看到很多java程序员朋友还在使用Spring 3.x,Spring MVC(struts),JSP.jQuery等这样传统技术.其实,我并不认为这些传统技术不好,而我想表达的是,技术的新旧程 ...

  2. spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发

     前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...

  3. vue+element-ui之tree树形控件有关子节点和父节点之间的各种选中关系详解

    做后端管理系统,永远是最蛋疼.最复杂也最欠揍的事情,也永远是前端开发人员最苦逼.最无奈也最尿性的时刻.蛋疼的是需求变幻无穷,如同二师兄的三十六般变化:复杂的是开发难度寸步难行,如同蜀道难,难于上青天: ...

  4. vue+element-ui实现表格checkbox单选

    公司平台利用vue+elementui搭建前端页面,因为本人第一次使用vue也遇到了不少坑,因为我要实现的效果如下图所示 实现这种单选框,只能选择一个,但element-ui展示的是多选框,check ...

  5. spring boot + vue + element-ui全栈开发入门

    今天想弄弄element-ui  然后就在网上找了个例子 感觉还是可以用的  第一步是完成了  果断 拿过来  放到我这里这  下面直接是连接  点进去 就可以用啊 本想着不用vue   直接导入连接 ...

  6. vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值。

    vue+elementUI项目,父组件向子组件传值,子组件向父组件传值,父子组件互相传值. vue 父组件与子组件相互通信 一.父组件给子组件传值 props 实现父组件向子组件传值. 1父组件里: ...

  7. VUE + ElementUI 从搭建到运行

    版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 前言:本文简洁的描述VUE + ElementUI 从搭建到运行,可以根据本文先搭建出可运行的项目,然后再详细回顾每个步骤所做的事: ...

  8. vue element-ui 日期选择器组件 日期时间格式化

    vue element-ui 组件开发大大提高了我们的效率,但有时候并不能满足我们的需求,例如时间,日期组件: element-ui 日期返回的格式是这样的,看下图: 但我们要的是另一个格式 , 如下 ...

  9. Java快速开发平台强大的代码生成器,JEECG 3.7.5 VUE+ElementUI SPA单页面应用版本发布

    JEECG 3.7.5 VUE+ElementUI SPA单页面应用版本发布 此版本为Vue+ElementUI SPA单页面应用版本,提供新一代风格代码生成器模板,采用Vue技术,提供两套精美模板E ...

随机推荐

  1. day16匿名函数

    匿名函数,好像也就是 lambda 表达式 先来看一段函数,返回 def func(n): return n * 3 print(func(5))15 用lambda表达式写: func = lamb ...

  2. 5.基于优化的攻击——CW

    CW攻击原论文地址——https://arxiv.org/pdf/1608.04644.pdf 1.CW攻击的原理 CW攻击是一种基于优化的攻击,攻击的名称是两个作者的首字母.首先还是贴出攻击算法的公 ...

  3. Redis常见面试题

    介绍:Redis 是一个开源的使用 ANSI C 语言编写.遵守 BSD 协议.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库,并提供多种语言的 API的非关系型数据库. 传统数据 ...

  4. eclipse 下载安装单元测试log4j的配置与搭建

    搭建log4j的具体步骤 1.下载jar包放在lib 拓展库中 百度云下载 地址 链接:https://pan.baidu.com/s/1Cvb22kCJcymORehwhKnCrQ 提取码:b55m ...

  5. 当linux报 “-bash: fork: 无法分配内存”

    “-bash: fork: 无法分配内存”,发现连了好多终端,然后断开了一个终端,然后这边终端可以敲命令了 [root@172.16.31.105 /home/www/test]# free -m  ...

  6. Vue H5 项目模板

    使用了 mint-ui sass vue fastclick vue router 一个项目的初始化状态,一个新项目,陆陆续续花了2天时间搭起来的. 里面有mint-ui的基本用法 tabbar 还有 ...

  7. jmeter(二十一)jmeter常用插件介绍

    jmeter作为一个开源的接口性能测试工具,其本身的小巧和灵活性给了测试人员很大的帮助,但其本身作为一个开源工具,相比于一些商业工具(比如LoadRunner),在功能的全面性上就稍显不足. 这篇博客 ...

  8. 转 InnoDB索引

    原文: http://blog.codinglabs.org/articles/theory-of-mysql-index.html InnoDB索引实现 虽然InnoDB也使用B+Tree作为索引结 ...

  9. (71)Wangdao.com第十一天_JavaScript 数学对象 Math

    Math 对象 封装了数学相关的 属性和方法. 和其他对象不一样,Math 不是一个构造函数,所以不能 new 生成实例, 其所有属性和方法都必须在 Math 对象上调用. 静态属性 Math.PI ...

  10. Servlet 参数

    1.应用参数,在web.xml配置,所有Servlet共用 <context-param> <param-name>driver</param-name> < ...