html5 多级侧边栏,vue+elementUI组件递归实现可折叠动态渲染多级侧边栏导航

本文介绍了如何使用Vue和ElementUI通过组件递归实现可折叠的动态侧边栏导航。在实现过程中,作者遇到了选中样式问题和折叠时的循环调用问题,通过分析和调试解决了这些问题。最终,通过简化组件结构和设置属性解决了所有bug,成功实现了功能。文章还提供了测试数据和实际效果截图。
摘要由CSDN通过智能技术生成

早就实现了功能,但是发现点击的时候,选中的菜单项背景色会变白,周五时候仔细观察了一下,发现并不是调整样式的问题,而是选项没有被选中,于是好好研究了一下组件递归这块,总结记录一下心路历程

一、概念

递归:递归其实说白了,就是自己调用自己,样子就像是套娃一个套一个的,小时候玩过一个游戏汉诺塔就是利用的递归原理:

743fefbd18f34f63f2fa6b1caa47282e.png

函数递归:函数利用函数名还调用自己

组件递归:所以组件递归利用的是vue组件中的name属性来实现的

二、需求

实现可折叠动态渲染多级侧边栏导航

三、分析

f448435a1c6190c9103df63c980115d6.png

1、观察到侧边栏导航是一级一级的,第二级就相当于再重复一遍第一级 2、有一个特点,有的菜单有下级,有的没有下一级 3、动态渲染,说明是从后台接口获取的树类型数据,动态的渲染上去 四、代码实现 1、首先先执行一下文档里的demo试一下:

2、改成自己需要的样式,第一次是这么写的

父组件SideBar

:collapse="sidebarFold" :collapseTransition="false" :unique-opened="true" @select="selectItem">

导航列表

{{item.name}}

{{item.name}}

export default {

name: 'SideBar',

components: {

SideBarItem: () => import('@/components/common/SideBarItem')

},

data () {

return {

}

},

mounted () {

},

methods: {

selectItem(name, path){

// alert(name)

this.$router.push(path)

this.$store.commit('common/updateMenuActiveName', name)

}

},

computed: {

menuList: {

get () {

return this.$store.state.common.menuList

},

set (val) {

this.$store.commit('common/updateMenuList', val)

}

},

menuActiveName: {

get () { return this.$store.state.common.menuActiveName },

set (val) { this.$store.commit('common/updateMenuActiveName', val) }

},

sidebarFold: {

get() {return this.$store.state.common.sidebarFold;},

set(val) {this.$store.commit("common/updateSidebarFold", val);}

},

},

}

.menu-wrap{

width: 200px;

min-height: 1020px;

background: url('../../assets/img/sidebar_bg.png') no-repeat;

background-size: 100% 100%;

}

/deep/ .el-menu{

background-color: transparent !important;

.iconfont {

font-size: 18px;

vertical-align: sub;

margin-right: 5px;

display: inline-block;

width: 20px;

text-align: center;

}

}

/deep/ .el-menu-item,

/deep/ .el-submenu__title{

color: #fff;

.iconfont{

color: #fff;

}

}

/deep/ .el-menu-item span,

/deep/ .el-submenu__title span{

padding-left: 10px;

}

/deep/ .el-menu-item.is-active {

-webkit-box-shadow: inset 5px 100px 0px -2px #0064B6;

box-shadow: inset 5px 100px 0px -2px #0064B6;

}

/deep/ .el-submenu__title:hover,

/deep/ .el-menu-item:hover{

background: #0064B6;

}

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

padding: 0;

}

子组件SideBarItem

export default {

name: 'SideBarItem',

// props: ['list'],

props: {

list: {

type: Array || ''

}

},

data () {

return {

treeData: [{

label: '某某省',

children: [{

label: '中共某某省委员会'

// children: [{

// label: '三级 1-1-1'

// }]

}, {

label: '中共某某省办公室'

}, {

label: '中共某某省组织部'

}

]

}

],

isShow: false

// menuList: []

}

},

mounted () {

this.loadSysMenu()

},

methods: {

loadSysMenu () {

// console.log('menu', this.menuList)

},

// personManage (name) {

// if (name === '人员管理') {

// this.isShow = !this.$store.state.common.rbflag

// // alert('111' + this.isShow)

// this.$store.commit('common/updateShowRbox', this.isShow)

// }

// },

selectItem(name, path){

// alert(name)

this.$router.push(path)

this.$store.commit('common/updateMenuActiveName', name)

}

},

}

.menu{

width: 100%;

.sub-menu-item /deep/ .el-submenu__title,

.menu-item{

height: 60px;

line-height: 60px;

text-align: left;

//padding-left: 30px !important;

//border-bottom: 1px solid #000;

//border-right: 1px solid #000;

color: #fff;

}

.sub-menu-item .el-menu-item{

padding-right: 0;

}

/deep/ .el-menu-item .is-active{

background-color: #0087df;

}

.menu-item:hover,

/deep/ .el-submenu__title:hover{

background-color: #0087df;

}

.menu-item span,

.sub-menu-item /deep/ .el-submenu__title>span{

font-weight: 700;

}

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

padding: 0 !important;

}

.menu-item-group .menu-item{

background: url('../../assets/img/sidebar_bg.png') no-repeat;

}

.el-menu-item-group span{

font-weight: normal;

}

}

后来发现折叠不成功,而且选中之后选中项样式没变,后来发现是没选中,研究发现是因为多嵌套了一层div,而且用了el-menu-item-group项目中并不需要这个,于是改进如下:

父组件SideBar

导航列表

export default {

name: 'SideBar',

components: {

SideBarItem: () => import('@/components/common/SideBarItem')

},

data () {

return {

}

},

mounted () {

},

methods: {

foldSideBar(){

this.sidebarFold = !this.sidebarFold

this.menuActiveName = 'NAV'

}

},

computed: {

menuList: {

get () {

return this.$store.state.common.menuList

},

set (val) {

this.$store.commit('common/updateMenuList', val)

}

},

menuActiveName: {

get () {

console.log(this.$store.state.common.menuActiveName)

return this.$store.state.common.menuActiveName

},

set (val) {

this.$store.commit('common/updateMenuActiveName', val)

}

},

sidebarFold: {

get() {return this.$store.state.common.sidebarFold;},

set(val) {this.$store.commit("common/updateSidebarFold", val);}

},

},

}

.menu-wrap{

width: 200px;

min-height: 1020px;

background: url('../../assets/img/sidebar_bg.png') no-repeat;

background-size: 100% 100%;

}

/deep/ .el-menu{

background-color: transparent !important;

.iconfont {

font-size: 18px;

vertical-align: sub;

margin-right: 5px;

display: inline-block;

width: 20px;

text-align: center;

}

}

/deep/ .el-menu-item,

/deep/ .el-submenu__title{

color: #fff;

.iconfont{

color: #fff;

}

}

/deep/ .el-menu-item span,

/deep/ .el-submenu__title span{

padding-left: 10px;

}

/deep/ .el-menu-item.is-active {

-webkit-box-shadow: inset 5px 100px 0px -2px #0064B6;

box-shadow: inset 5px 100px 0px -2px #0064B6;

}

/deep/ .el-submenu__title:hover,

/deep/ .el-menu-item:hover{

background: #0064B6;

}

子组件SideBarItem

{{ menu.name }}

{{ menu.name }}

export default {

name: 'SideBarItem',

// props: ['menu'],

props: {

menu: {

type: Object || {}

}

},

data () {

return {

}

},

mounted () {

},

methods: {

selectItem(code, path){

// alert(name)

console.log(code, path)

this.$router.push(path)

this.$store.commit('common/updateMenuActiveName', code)

}

},

}

.menu{

width: 100%;

.menu-item{

height: 60px;

line-height: 60px;

text-align: left;

color: #fff;

}

.sub-menu-item .el-menu-item{

padding-right: 0;

}

/deep/ .el-menu-item .is-active{

background-color: #0087df;

}

.menu-item:hover{

background-color: #0087df;

}

.menu-item span{

font-weight: 700;

}

}

功能基本实现,但是出现一个bug,当鼠标点折叠时,会出现循环调用某个事件,导致栈溢出报错,查看文章只需对子菜单设置属性 :popper-append-to-body=“false” 即可

参考文章:Element-ui NavMenu子菜单使用递归生成时使用报错

最后附上简单的测试数据:

testData: [

{"id":"34161C2E8-7348-4439-8899-9A8039AE6AE4","pid":"0","code":"HOME","name":"首页","path":"/home","type":null,"icon":null,"sysId":"2761C2E8-7348-4439-8899-9A8039AE6AE3","orderNo":0,"isCheck":null,"children":[]},

{"id":"703DBEBD-F92C-4347-9203-F60A73153C3F","pid":"0","code":"WD","name":"温度","path":"/temperature","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,"children":[]},

{"id":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","pid":"0","code":"BJ","name":"报警","path":"/alarm","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,

"children":[

{"id":"1C99333D-886F-4AD6-93C4-7C5244E48247","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"FD","name":"防盗","path":"/burg","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},

{"id":"1DBDF678-F51F-444A-B995-61E5D9CCA5AF","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"JL","name":"警铃","path":"/bell","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},

{"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF481","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"JS","name":"浸水","path":"/immersion","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},

{"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF482","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"MJ","name":"门禁","path":"/punch","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},

{"id":"BFC8C2E1-0E5B-4EEE-B91D-3DABC63FF483","pid":"73660AB4-48D3-4BDB-86FD-C8397D4D54EC","code":"ZT","name":"状态","path":"/state","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]}

]

},

{"id":"34161C2E8-7348-4439-8899-9A8039AE6AE5","pid":"0","code":"GZ","name":"工作","path":"/work","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,

"children":[]

},

{"id":"0CD6B09A-AA43-4AE9-9AC7-29BC5AC83495","pid":"0","code":"SJ","name":"数据","path":"/data","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,

"children":[]

},

{"id":"049C670D-A33E-4188-9206-B3F3B5DDE77B","pid":"0","code":"SP","name":"视频","path":"/video","type":null,"icon":null,"sysId":"3691C2E8-8848-4439-8899-9A8039AE6AB5","orderNo":0,"isCheck":null,"children":[]},

{"id":"0A15DBB6-3241-4C7F-AAD4-5417E7BBECAA","pid":"0","code":"RZ","name":"日志","path":"/log","type":null,"icon":null,"sysId":"2AB00274-73DF-459A-A02E-C79A4D8A8929","orderNo":0,"isCheck":null,

"children":[]

}

]

效果如图:

e72c36213ecf024b772e2a6298fe2b15.png

折叠后如图:

6ba8cb3e81eb489836ab4d62eae2fb47.png

到此这篇关于vue+elementUI组件递归实现可折叠动态渲染多级侧边栏导航的文章就介绍到这了,更多相关elementUI可折叠动态侧边栏导航内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值