element
element copied to clipboard
[Bug Report] El-submenu causes 'Maximum call stack exceeded' error in collapsed menu if it's the top element of a component
Element UI version
2.12.0
OS/Browsers version
Windows 10 OS Version 1809 (Build 17763.805) / 78.0.3904.70 (Official Build) (64-bit) (cohort: 78_70_Win)
Vue version
2.6.10
Reproduction Link
https://codepen.io/mik-jozef-artin/pen/abbYNza
Steps to reproduce
- Open the reproduction link.
- Place mouse on the menu (ie. the text 'title')
The error 'Maximum call stack size exceeded' will appear in the console.
It seems to me that these conditions are all necessary for the issue to manifest:
- Menu must be collapsed (the
collapse
prop onel-menu
must betrue
) - Submenu must be in a separate component (in this case
customized-menu-item
) - The submenu must be the top element in the separate component.
- Attribute
:popper-append-to-body="true"
must be present on the submenu
Fortunately, the second condition provides an easy workaround - placing the submenu inside a div
will suppress the issue. This behavior is still surprising and I guess unwanted.
What is Expected?
No errors.
What is actually happening?
Uncaught RangeError: Maximum call stack size exceeded.
same issue!
@element-bot 希望可以修复这个问题 应用场景还是蛮多的
same issue
mark
I fixed this bug by rewirte method "handleMouseenter" of el-submenu in self-module . (sorry for the format, I can't fix it.)
The easiest way is setting :popper-append-to-body="false" . If you have to append to body, you can try the follow code :
mounted() {
let redefine_el_submenu_handleMouseenter = function (event) {
// ignore some original handleMouseenter code, please parse by yourself.//
if (this.appendToBody && this.$parent.$el !== event.target) {
this.$parent.$el.dispatchEvent(new MouseEvent('mouseenter'));
}
}
this.$children[0].handleMouseenter = (event) => {
redefine_el_submenu_handleMouseenter.call(this.$children[0], event)
}
}
same issue
hope fix it ~~
Still unfixed oficially
出问题代码 SideBarMenu/index.vue代码:
<template>
<el-menu
:collapse="closedSideBar"
background-color=""
text-color=""
active-text-color=""
:default-active="'/home'"
router
>
<side-bar-menu-item
v-for="(routeItem, index) in routeList"
:key="index"
:route-item="routeItem"
></side-bar-menu-item>
</el-menu>
</template>
<script>
import SideBarMenuItem from "./components/SideBarMenuItem";
import mixins from "../mixins";
export default {
name: "SideBarMenu",
mixins: [mixins],
components: {
SideBarMenuItem,
},
data() {
return {
routeList: [
{ path: "/home", title: "路由1" },
{
path: "2",
title: "路由2",
children: [
{ path: "/about", title: "路由2-1" },
{
path: "2-2",
title: "路由2-2",
children: [{ path: "2-2-1", title: "路由2-2-1" }],
},
],
},
],
};
},
};
</script>
<style lang="scss" scoped>
.el-menu {
border: none;
}
</style>
SideBarMenu/components/SideBarMenuItem/index.vue代码:
<template>
<el-submenu v-if="routeItem.children && routeItem.children.length" :index="routeItem.path">
<template #title>
<i class="el-icon-menu"></i>
<span>{{ routeItem.title }}</span>
</template>
<side-bar-menu-item
v-for="(item, index) in routeItem.children"
:key="index"
:route-item="item"
></side-bar-menu-item>
</el-submenu>
<el-menu-item v-else :index="routeItem.path">
<i class="el-icon-menu"></i>
<template #title>
<span>{{ routeItem.title }}</span>
</template>
</el-menu-item>
</template>
<script>
export default {
name: "SideBarMenuItem",
props: {
routeItem: {
type: Object,
},
},
};
</script>
解决方案: 直接使用渲染函数渲染本问题可以完美解决
import Vue from "vue";
import mixins from "../mixins";
const createSideBarMenuItem = (createElement, routeList) => {
return routeList.map((routeItem) => {
if (routeItem.children && routeItem.children.length) {
return createElement(
"el-submenu",
{
props: {
index: routeItem.path,
},
},
[
createElement(
"template",
{
slot: "title",
},
[
createElement("i", {
class: "el-icon-menu",
}),
createElement("span", {
domProps: {
innerHTML: routeItem.title,
},
}),
]
),
createSideBarMenuItem(createElement, routeItem.children),
]
);
} else {
return createElement(
"el-menu-item",
{
props: {
index: routeItem.path,
},
},
[
createElement("i", {
class: "el-icon-menu",
}),
createElement("span", {
slot: "title",
domProps: {
innerHTML: routeItem.title,
},
}),
]
);
}
});
};
const SideBarMenu = Vue.component("SideBarMenu", {
render(createElement) {
return createElement(
"el-menu",
{
style: {
border: "none",
},
mixins: [mixins],
props: {
router: true,
collapse: this.closedSideBar,
},
},
createSideBarMenuItem(createElement, this.routeList)
);
},
props: {
routeList: {
type: Array,
default: () => [
{ path: "/home", title: "路由1" },
{
path: "2",
title: "路由2",
children: [
{ path: "/about", title: "路由2-1" },
{
path: "2-2",
title: "路由2-2",
children: [{ path: "2-2-1", title: "路由2-2-1" }],
},
],
},
],
},
closedSideBar: {
type: Boolean,
default: true,
},
},
});
export default SideBarMenu;
this.$parent.$el !== event.target
It's always true on my side
https://blog.csdn.net/qq_34452824/article/details/106546478
fix it by hack, but it,s not very good
+1
+1
有一个不钳充钱就能玩的游戏,http://www.0vslu5.cn ,听说信用很好的,我们去玩两把吧,反正没有风险。<狄/p>
我也遇到了。 目前在网上找到两个方法: 1.外层添加div包裹 2.popper-append-to-body设置为false 但是两种解决方案,都会导致其他副作用。还望官方能够修复下..