

recursionMenu.vue
<template>
<!-- 有子菜单------------------------------------------>
<el-submenu
v-if="(item.children || []).length"
:popper-class="popper_class"
:show-timeout="show_timeout"
:hide-timeout="hide_timeout"
:key="item.path || item.label"
:index="item.path || item.label"
:divide="item.divide"
>
<template slot="title">
<!-- 主菜单图标 -->
<i :class="item.icon" :style="item.style" />
<!-- 主菜单文字 -->
<span :style="item.style">{{ item.label }}</span>
<el-badge
v-if="item.badge"
:is-dot="!item.badge.value"
:value="item.badge.value"
:type="item.badge ? item.badge.type : `danger`"
/>
</template>
<recursionMenu
v-for="(item, i) in item.children"
:key="item.path || item.label"
:data="{
item,
show_timeout: show_timeout,
hide_timeout: hide_timeout,
popper_class: popper_class,
}"
/>
</el-submenu>
<!-- 没有子菜单------------------------------------------>
<el-menu-item
v-else
:key="`leaf-${item.path || item.label}`"
:index="item.path || item.label"
:divide="item.divide"
>
<!-- 主菜单图标 -->
<i :class="item.icon" :style="item.style" />
<!-- 主菜单文字 -->
<span :style="item.style">{{ item.label }}</span>
<el-badge
v-if="item.badge"
:is-dot="!item.badge.value"
:value="item.badge.value"
:type="item.badge ? item.badge.type : `danger`"
/>
</el-menu-item>
</template>
<script>
export default {
name: `recursionMenu`,
components: {},
data() {
return {
item: {},
popper_class: ``,
show_timeout: 300,
hide_timeout: 300,
};
},
props: ["data"],
computed: {},
watch: {
data: {
handler(newValue, oldValue) {
// console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
if (Object.keys(newValue || {}).length) {
this.form = JSON.parse(JSON.stringify(newValue));
this.$g.convertForm2ComponentParam(`item`, this);
this.$g.convertForm2ComponentParam(`popper_class`, this);
this.$g.convertForm2ComponentParam(`show_timeout`, this);
this.$g.convertForm2ComponentParam(`hide_timeout`, this);
}
},
deep: true, //深度监听
immediate: true, //立即执行
},
},
created() {},
mounted() {
// 将该行代码放到能够顺利执行的地方就可以,本示例中放到了mounted中
// 由于这种错误只发生在template下只有一个el-submenu这种情况,因此this.$children[0]就是该el-submenu
this.$children[0].$parent = this.$parent;
},
beforeDestroy() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.recursionMenu {
}
</style>
demo
<template>
<div :class="$options.name">
<el-menu
:class="$options.name"
:collapse="collapse"
:default-active="default_active"
:default-openeds="default_openeds"
:mode="mode"
@select="select"
>
<recursionMenu
v-for="(item, i) in menu"
:key="i"
:data="{
item,
show_timeout: show_timeout,
hide_timeout: hide_timeout,
popper_class: `admin_v2-top-submenu${collapse ? `-collapse` : ``}`,
}"
/></el-menu>
</div>
</template>
<script>
import recursionMenu from "@/vue/admin/recursionMenu";
export default {
name: `topMenu`,
components: { recursionMenu },
data() {
return {
collapse: null,
default_active: null,
default_openeds: [], //默认展开的菜单index数组
menu: [],
mode: `horizontal`,
select: null,
show_timeout: 300,
hide_timeout: 300,
};
},
props: ["data"],
computed: {},
watch: {
data: {
handler(newValue, oldValue) {
// console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
if (Object.keys(newValue || {}).length) {
let select = newValue.select;
this.select = select;
delete newValue.select;
this.form = JSON.parse(JSON.stringify(newValue));
this.$g.convertForm2ComponentParam(`isSubMenu`, this);
this.$g.convertForm2ComponentParam(`collapse`, this);
this.$g.convertForm2ComponentParam(`default_active`, this);
this.$g.convertForm2ComponentParam(`default_openeds`, this);
this.$g.convertForm2ComponentParam(`menu`, this);
this.$g.convertForm2ComponentParam(`mode`, this);
this.$g.convertForm2ComponentParam(`show_timeout`, this);
this.$g.convertForm2ComponentParam(`hide_timeout`, this);
}
},
deep: true, //深度监听
immediate: true, //立即执行
},
navList: {
handler(newValue, oldValue) {
//console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
if (Object.keys(newValue || {}).length) {
this.collapse_navList = [
{
label: `菜单`,
icon: "el-icon-menu",
// ID: "MENU-ROOT",
// "PID": "SRManagePermissions",
// "leaf": false,
children: this.navList,
},
];
}
},
deep: true, //深度监听
immediate: true, //立即执行
},
},
created() {},
mounted() {},
beforeDestroy() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.topMenu {
>>> .el-menu {
background-color: transparent;
$menu-height: 50px;
.el-icon-menu {
color: white;
}
$active-background: radial-gradient(100% 80% at 50% 100%, #ffffff66, transparent 50%);
.el-menu-item,
.el-submenu__title {
height: $menu-height;
line-height: revert;
display: flex;
justify-content: center;
align-items: center;
padding: 0 10px;
color: white !important;
border-bottom: none !important;
transition: none;
// 选中菜单、聚焦菜单、移入菜单
&.is-active,
&:focus,
&:hover {
background: $active-background;
}
}
// 有子菜单的
.el-submenu__title {
cursor: default;
}
.el-submenu {
&.is-active {
& > .el-submenu__title {
background: $active-background;
}
}
}
.el-submenu__icon-arrow {
display: none;
}
}
}
</style>
<style lang="scss">
.admin_v2-top-submenu,
.admin_v2-top-submenu-collapse {
transition: none !important; //去掉下拉菜单动画
transform: translateX(-10px);
// 有子菜单的
.el-submenu__title {
cursor: default;
}
.el-menu-item {
display: flex;
justify-content: center;
align-items: center;
padding: 0 20px !important;
transition: none;
&.is-active {
pointer-events: none;
background-color: #409eff !important;
color: white !important;
}
&:hover {
background-color: #ecf5ff;
color: #66b1ff !important;
}
}
}
.admin_v2-top-submenu-collapse {
.el-menu-item {
justify-content: flex-start;
}
.el-submenu {
padding: 0 20px;
.el-menu-item {
min-width: revert;
}
.el-submenu__title {
display: flex;
align-items: center;
padding: 0 !important;
.el-submenu__icon-arrow {
position: static;
margin-top: revert;
margin-left: 10px;
}
}
&.is-active {
background-color: #409eff;
& > .el-submenu__title {
background-color: transparent;
& > * {
color: white;
}
}
}
}
}
</style>
解决报错el-menu子菜单鼠标移入报“Maximum call stack size exceeded.“错误原因及解决方法-CSDN博客文章浏览阅读25次。【代码】el-menu子菜单鼠标移入报“Maximum call stack size exceeded.“错误原因及解决方法。
https://blog.csdn.net/qq_37860634/article/details/147758875