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

比如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. Nginx服务器中的Socket切分,需要的朋友可以参考下

    NGINX发布的1.9.1版本引入了一个新的特性:允许使用SO_REUSEPORT套接字选项,该选项在许多操作系统的新版本中是可用的,包括DragonFly BSD和Linux(内核版本3.9及以后) ...

  2. 《XXX重大技术需求征集系统》的可用性和可修改性战术分析

    在网站的界面完整有效的呈现在最终用户面前前,其中经历的每一环节出现问题都会导致网站页面不可访问.原因如,如DNS被劫持.网站交换机失效,硬盘损坏,网卡松掉,机房停电等都可能导致网站不可用(网站故障)情 ...

  3. 习题集1a:研究方法入门

    1.课程实践编号 课程实践编号 随着对习题集“PS 1a:研究方法入门”和其他习题集的了解,你可能会发现进度栏中的习题编号并非一直是连续的. 对于存在两个习题集的课程,如果一个习题集看上去“缺失”习题 ...

  4. fastadmin表单验证

    Unexpected token < in JSON at position 0 注意: if (!form.is("form"))//form的选择器不是form直接返回所 ...

  5. sql防止注入

    使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入.在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才 ...

  6. DDoS攻击与防御(3)

    3.攻击应用资源网络应用和服务在处理数据时,通常需要消耗一定的网络连接.计算和存储资源,这些资源是由应用程序向系统进行申请并自行管理和维护的.消耗应用资源的DDoS攻击就是通过向应用提交大量消耗资源的 ...

  7. SpringBoot使用Nacos服务发现

    本文介绍SpringBoot应用使用Nacos服务发现. 上一篇文章介绍了SpringBoot使用Nacos做配置中心,本文介绍SpringBoot使用Nacos做服务发现. 1.Eureka闭源 相 ...

  8. every循环

    一.语法 var result = myArr.every(function(item, index){ return item>0; }) //全部满足,才为true every方法检测数组中 ...

  9. java判断通常的逻辑

    package com.stylefeng.guns.core.common.constant.factory; import com.baomidou.mybatisplus.mapper.Enti ...

  10. CSS3_天猫商品墙

    天猫商品墙 网格状布局: 1.  ul li 布局 2.  float: left; 使得元素在一行.注意: 父元素解决高度塌陷 3.  ul 设置固定宽,使得元素挤下去 4.  给父元素加一个 pa ...