[element-ui] elementUI-NavMenu 导航菜单动态渲染(递归)

彩蛋:后台管理系统一站式平台模板

vue-next-admin,这是基于 vue3.x + CompositionAPI + typescript + vite + element plus + vue-router-next + next.vuex,适配手机、平板、pc 的后台开源免费模板库

一、效果图

支持横向导航请看这篇
在这里插入图片描述

二、组件部分

注意:<sub-menu :menu-list="val[props.children]" :props="props" @getmenu="onMenuItemClick"/>。递归调用当前组件

Vue.component('sub-menu', {
	template: `
			<div>
				<div v-for="(val, key) in menuList" :key="key">
					<el-submenu :index="val[props.index]" v-if="val[props.children] && val[props.children].length > 0">
						<template slot="title">
							<i :class="val.icon"></i>
							<span>{{val[props.label]}}</span>
						</template>
						<sub-menu :menu-list="val[props.children]" :props="props" @getmenu="onMenuItemClick"/>
					</el-submenu>
					<el-menu-item :index="val[props.index]" v-else @click="onMenuItemClick(val)">
						<i :class="val.icon"></i>
						<span slot="title">{{ val[props.label] }}</span>
					</el-menu-item>
				</div>
			</div>
		`,
	props: {
		menuList: {
			type: Array,
			default () {
				return []
			}
		},
		props: {
			type: Object,
			default () {
				return {
					children: 'children',
					label: 'label',
					index: 'id'
				}
			}
		}
	},
	methods: {
		onMenuItemClick(item) {
			this.$emit('getmenu', item)
		}
	}
})
三、页面调用
<el-menu default-active="/demo133">
	<sub-menu :menu-list="list" :props="defaultProps" @getmenu="onGetMenu" />
</el-menu>
四、属性说明
4.1 Attributes
属性名类型默认值说明
menuListArray[]菜单列表数据
4.2 props

参考:element tree:props="defaultProps"

属性名类型默认值说明
childrenString‘children’指定子树为节点对象的某个属性值
labelString‘label’指定节点标签为节点对象的某个属性值
indexString‘id’唯一标志
4.3 Events
属性名说明回调参数
getmenu获取当前点击项内容obj
五、全部html

直接复制,新建xxx.html文件,直接执行

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>elementUI-NavMenu 导航菜单动态渲染(递归)</title>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
		<script src="https://unpkg.com/element-ui/lib/index.js"></script>
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<style>
			* {
				margin: 0;
				padding: 0;
				box-sizing: border-box;
			}

			html,
			body,
			#app {
				width: 100%;
				height: 100%;
			}

			.warp-container {
				width: 100%;
				height: 100%;
				display: flex;
			}

			.warp-left {
				width: 240px;
				height: 100%;
				border-right: 1px solid #e6e6e6;
			}

			.warp-right {
				flex: 1;
			}
			
			.el-scrollbar__wrap {
				overflow-x: hidden;
			}
			
			.el-menu {
				border-right: none;
			}
			
			.flex {
				display: flex;
			}
			
			.flex-auto {
				flex: 1;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<div class="warp-container">
				<el-scrollbar class="warp-left" ref="scrollbarRef">
					<el-menu default-active="/demo133">
						<sub-menu :menu-list="list" :props="defaultProps" @getmenu="onGetMenu" />
					</el-menu>
				</el-scrollbar>
				<el-scrollbar class="warp-right" ref="scrollbarRef">
					<div class="flex">
						<div flex="flex-auto">
							<pre>
								{{ list }}
							</pre>
						</div>
						<div flex="flex-auto" style="padding-top: 30px;">
							<span>选中的数据:</span>
							<pre>
								{{ selMenuData }}
							</pre>
						</div>
					</div>
				</el-scrollbar>
			</div>
		</div>

		<script type="text/javascript">
			Vue.component('sub-menu', {
				template: `
						<div>
							<div v-for="(val, key) in menuList" :key="key">
								<el-submenu :index="val[props.index]" v-if="val[props.children] && val[props.children].length > 0">
									<template slot="title">
										<i :class="val.icon"></i>
										<span>{{val[props.label]}}</span>
									</template>
									<sub-menu :menu-list="val[props.children]" :props="props" @getmenu="onMenuItemClick"/>
								</el-submenu>
								<el-menu-item :index="val[props.index]" v-else @click="onMenuItemClick(val)">
									<template slot="title">
										<i :class="val.icon"></i>
										<span>{{val[props.label]}}</span>
									</template>
								</el-menu-item>
							</div>
						</div>
					`,
				props: {
					menuList: {
						type: Array,
						default () {
							return []
						}
					},
					props: {
						type: Object,
						default () {
							return {
								children: 'children',
								label: 'label',
								index: 'id'
							}
						}
					}
				},
				methods: {
					onMenuItemClick(item) {
						this.$emit('getmenu', item)
					}
				}
			})

			const vm = new Vue({
				el: '#app',
				data() {
					return {
						selMenuData: {},
						defaultProps: {
							children: 'aaa',
							label: 'title',
							index: 'path'
						},
						list: [{
								id: 1,
								title: '测试1',
								path: '/demo1',
								icon: 'el-icon-location',
								aaa: [{
										id: 12,
										title: '测试12',
										path: '/demo12',
										icon: 'el-icon-location',
										aaa: [{
											id: 122,
											title: '测试122',
											path: '/demo122',
											icon: 'el-icon-location',
										}]
									},
									{
										id: 13,
										title: '测试13',
										path: '/demo13',
										icon: 'el-icon-location',
										aaa: [{
											id: 133,
											title: '测试133',
											path: '/demo133',
											icon: 'el-icon-location',
										}]
									}
								]
							},
							{
								id: 2,
								title: '测试2',
								path: '/demo2',
								icon: 'el-icon-location',
								aaa: []
							},
							{
								id: 3,
								title: '测试3',
								path: '/demo3',
								icon: 'el-icon-location',
								aaa: [{
										id: 31,
										title: '测试31',
										path: '/demo31',
										icon: 'el-icon-location',
									},
									{
										id: 32,
										title: '测试32',
										path: '/demo32',
										icon: 'el-icon-location',
									}
								]
							}
						]
					}
				},
				methods: {
					onGetMenu(item) {
						this.selMenuData = item
						// this.$router.push({
						// 	path: item.path,
						// 	query: {
						// 		t: new Date().getTime()
						// 	}
						// })
					}
				}
			})
		</script>
	</body>
</html>
``
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值