vue 自定义侧边栏 递归无限子级菜单

有很多网站会涉及到导航栏,我自己在开发中用的是element导航组件,并且自定义事件,给大家分享一下。

1.使用递归方法,无限循环子级菜单。

2.使用组件封装,维护方便。

3.使用index作为路由跳转。

4.结合后台动态渲染。

5.自定义样式,修改默认icon。

6.根据后台返回数据,动态设置默认选中。



 1.封装组件。

  首先创建好vue之后,在a_module里创建一个存放组件的文件夹,因为a_module是存放公共资源以及静态文件的,当然也可以根据喜好来创建。




2.调用组件。

  在要使用到的页面中使用 import 引入封装好的组件,components初始化一下,在页面中使用。






注意:这里需要注意的是,在引用的页面中一定要el-menu包裹起来,可以在el-menu标签里来配置侧边栏的各种状态。

3.组件传值



 我是后台拿到的数据,当然也可以自定义数据,在引用组建的页面内创建,在子组件标签上边自定义事件,在子组件用props接收参数。



 4.el-menu配置

  这里呢,需要在父组件内配置侧边栏的各种状态,选中状态啦,index路由跳转啦,等等。



   这里呢,我主要配置了,router:开启index跳转路由,default-active:默认选中,这里呢我做了很多判断,大家可以根据实际情况来做处理,我主要是拿到当前地址,来做选中状态。active-text-color:配置字体颜色,等等

5.子组件递归,无限循环子级

我呢用的是递归的方法,他的原理呢就是自己调用自己。



 注意看红色框中的内容,

(1).大家可以看到,我在跟标签里边写了一个:class,主要原因就是,但你循环自己的时候,设置css样式只会生效一次,这个可以解决这个问题。

(2).然后呢,根据数据结构,循环父组件传递过来的参数,如果没有children的话,循环下边的代码,不调用子级,如果有children的话证明有子级菜单,那么调用上边代码。

(3).大家可以看到在label标签里我又调用了自己,然后传递参数,这里就是递归,如果满足条件就无线调用自己。

(4).这里呢我用了自定义图标,大家可以观察我的布局。

(5).到这里已经差不多了,但是要注意的是,:index,接受的是字符串形式的值,所以这里比较坑,需要的话可以用String()转化一下。

(6).至于图片里getImgUrl()方法,是解决图片异步的一种方法。



 6.默认样式

很多框架的默认样式是很难修改的,大家可以在页面中去找的class类名去修改,我用的是 /deep/ 这个是一个深度修饰符 或者是 >>> ,当然也可以在跟文件里去修改样式,但是我不建议这样去做,因为会他是全局修改,容易影响其他页面的样式。


差不多就是这些了,样式的以及源码我在下边给大家附上。

父组件:

html:

<el-menu

:router="true"

:default-active="(this.$route.meta[0].meta&&this.$route.meta[0].meta[0].path&&!this.$route.meta[0].meta[0].ispath)?this.$route.meta[0].meta[0].path:this.$route.meta[0].path"

active-text-color="#ffffff"

:unique-opened="true"

background-color="#00bfb8"

>

<menutree :data="navigation" class="hr_one"></menutree>

<!-- 侧边导航组件 -->

</el-menu>


css:

.el-aside::-webkit-scrollbar {

width: 4px;

background: #00d2ca;

}

.el-aside::-webkit-scrollbar-thumb {

background: #009d97;

border-top-right-radius: 10px;

border-top-left-radius: 10px;

border-bottom-right-radius: 10px;

border-bottom-left-radius: 10px;

}

.el-main::-webkit-scrollbar {

display: none;

}

.el-aside {

text-align: center;

position: absolute;

top: 80px;

bottom: 0;

left: 0;

background-color: #00bfb8 !important;

min-height: 800px;

.el-menu-item-group /deep/.el-menu-item-group__title {

padding: 0 !important;

}

.el-menu-item:hover {

background-color: #00d2ca;

}

.child_li {

color: #ffff;

display: flex;

align-items: center;

padding: 0;

span:first-child {

margin-left: 23px;

}

span:last-child {

margin-left: 23px;

}

}

}

josn:

这个数据呢,是我自己模拟的数据

navigation: [

{

 id:0,

 name: "首页",

 path: "/Hr-index/home",

icon: "icon_hrIndex.png"

 },

 {

 id:1,

 name: "教职工档案",

path: "/Hr-index/staffFiles",

icon: "icon_staffFiles.png"

},

 {

 id:2,

 name: "招聘信息",

 path: "",

 icon: "icon_hrJion.png",

 children: [

 { id: 122, name: "招聘申请", path: "/Hr-index/zpApply" },

 { id: 123, name: "招聘审核", path: "/Hr-index/zpCheck" },

 { id: 124, name: "结果统计", path: "/Hr-index/resultInfo" }

 ]

 },

 {

 id: 10,

 name: "解聘信息",

 path: "",

 icon: "icon_hrunBind.png",

 children: [

 { id: 119, name: "解聘信息", path: "/Hr-index/decruitment" },

 { id: 121, name: "解聘教师端", path: "/Hr-index/jpteacher" }

 ]

 },

 {

 id: 3,

 name: "劳资管理",

 path: "",

 icon: "icon_hrLabour.png",

 children: [

 { id: 117, name: "劳资详情", path: "/Hr-index/labour/details" },

 {

 id: 118,

 name: "岗位劳资设定",

 path: "/Hr-index/labour/setting"

 }

 ]

 },

 {

 id: 4,

 name: "考勤管理",

 path: "/Hr-index/check/manage",

 icon: "icon_manage.png"

 },

 {

 id: "5",

 name: "培训管理",

 path: "/Hr-index/modlifyift",

 icon: "icon_modifyift.png"

 },

 {

 id: "6",

 name: "离岗创业管理",

 path: "/Hr-index/Quit",

 icon: "icon_dimission.png"

 },

 {

 id: "7",

 name: "护照管理",

 icon: "icon_Passport.png",

 path: "/Hr-index/Passport"

 },

 {

 id: "8",

 name: "权限管理",

 icon: "icon_jurisdiction_li.png",

 path: "",

 children: [

 { id: "115", name: "人员管理", path: "/Hr-index/Jurisdiction_set" },

 { id: "116", name: "角色管理", path: "/Hr-index/Jurisdiction_role" }

 ]

 },

 {

 id: "11",

 name: "院系专业管理",

 path: "/Hr-index/yxhome",

 icon: "icon_yxhome.png"

 },

 {

 id: "",

 name: "课程管理",

 path: "/Hr-index/KcAdministration",

 icon: "icon_KcAdministration.png"

 },

 {

 id: "9",

 name: "个人信息",

 icon: "icon_Personal_li.png",

 path: "",

 children: [

 {

 id: "111",

 name: "个人档案rerwerwerwerwerwerwerwerwerwerwerwerwerwerwerwer",

 path: "/Hr-index/Personal_file"

 },

 { id: "112", name: "个人考勤", path: "/Hr-index/Personal_check" },

 { id: "113", name: "劳资详情", path: "/Hr-index/Personal_labour" },

 { id: "114", name: "培训详情", path: "/Hr-index/Personal_train" }

 ]

 }

], //导航数组

子组件:


html:

<div class="menutree" :class="[calssName]">

<div class>

<label v-for="menu in data" :key="menu.index">

<el-submenu :index="String(menu.id)" v-if="menu.children!=''">

<!-- <el-submenu :index="String(menu.id)" v-if="menu.children"> -->

<template slot="title">

<img :src="getImgUrl(menu.icon)" alt v-if="menu.icon" />

<span>{{menu.name}}</span>

</template>

<label>

<menutree :data="menu.children" :calssName="calssName"></menutree>

</label>

</el-submenu>

<el-menu-item :index="menu.path" v-else>

<img :src="getImgUrl(menu.icon)" alt v-if="menu.icon" />

<span

style="display:block;width:4px;height:4px;background:#ffffff;margin-top:28px;margin-left:30px; border-radius:100%;"

:style="{backgroundColor:calssName=='listtxt'?'#a6160a':'#ffffff',}"

v-else

></span>

<span

slot="title"

style="display:block;overflow: hidden;text-overflow:ellipsis;white-space: nowrap;white-space : nowrap;"

>{{menu.name}}</span>

</el-menu-item>

</label>

</div>

</div>



script:


import menutree from "./boss";

export default {

name: "menutree",

data() {

return {

menu_data: {},

name: "one"

};

},

components: {

menutree: menutree

},

props: ["data","calssName"],

mounted() {

// console.log(this.$route);

},

methods: {

getImgUrl(icon) {

return require("@/assets/" + icon);

}

}

};



css:


.menutree /deep/ .el-menu-item,

.menutree /deep/ .el-submenu__title {

color: #ffffff !important;

height: 60px;

line-height: 60px;

display: flex;

text-align: left;

padding: 0;

img {

width: 16px;

height: 16px;

float: left;

margin-top: 21px;

margin-left: 39px;

}

span {

float: left;

margin-left: 12px;

}

}

.one /deep/ .el-menu {

background: none;

}

.listtxt.menutree /deep/ .el-menu-item,.listtxt.menutree /deep/ .el-submenu__title {

color: #a6160a !important;

}


好啦,就到这里了,有不明白的地方可以跟我留言,我是前端菜鸡儿,嘻嘻嘻嘻。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容