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

比如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. aspnet core运行后台任务

    之前在公司的一个项目中需要用到定时程序,当时使用的是aspnet core提供的IHostedService接口来实现后台定时程序,具体的示例可去官网查看.现在的dotnet core中默认封装了实现 ...

  2. Loadrunner乱码问题解决方案(录制&&运行)

    在使用Loadrunner录制和回放时有时会出现乱码,从而导致脚本运行失败,这让我们很难定位脚本问题所在. 1.乱码产生的原因 1)loadrunner工具使用的是UTF-8编码,但被测系统使用的是G ...

  3. Django与ajax、分页器

    ajax简单数据响应 ajax请求,后台只需要返回信息,所以不会出现render.redirect 模板层: $('.btn').click(function() { $.ajax({ url: '/ ...

  4. Linux——目录和文件

    目录和文件

  5. jQuery 获取不到 kindeditor 内容 的解决方法

    错误写法 :  var content = $('#Content').val(); 正确写法: var content = $(document.getElementsByTagName(" ...

  6. MVC 微信开发获取用户OpenID

    第一次开发微信版网页,对最重要的获取微信OpenId,特此记录下来 1.首先得有appid和appsecret . public class WeiXin { public static string ...

  7. Django中的Form表单验证

    回忆一下Form表单验证的逻辑: 前端有若干个input输入框,将用户输入内容,以字典传递给后端. 后端预先存在一个Form表单验证的基类,封装了一个检测用户输入是否全部通过的方法.该方法会先定义好错 ...

  8. (56)Wangdao.com第八天_JavaScript 流程控制语句

    流程控制语句 条件判断语句 if 条件分支语句 switch 循环语句 for .while switch 和 if 都可以相互转换,switch 的性能更优于 if 1. 条件判断语句 if 在某条 ...

  9. python 生成器generator

    关于生成器,主要有以下几个 关键点的内容 一.什么是generator ,为什么要有generator? 二.两种创建生成器方式 三.yield关键字 四.generator 两个调用方法 next( ...

  10. 廖雪峰Python3笔记

    主要复习过一遍 简介 略 安装 略 *** 第一个Python程序 第一行的注释: # _*_ coding: utf-8 _*_ #!/usr/bin/env python3 print() 可以接 ...