詳解Element-ui NavMenu子菜單使用遞歸生成時使用報錯
當(dāng)采用遞歸方式生成導(dǎo)航欄的子菜單時,菜單可以正常生成,但是當(dāng)鼠標hover時,會出現(xiàn)循環(huán)調(diào)用某個(mouseenter)事件,導(dǎo)致最后報錯
處理方式
注:2.13.2 版本,只需對子菜單設(shè)置屬性 :popper-append-to-body="false" 就不會出現(xiàn)這個問題了
報錯信息如下:
Uncaught RangeError: Maximum call stack size exceeded.
at VueComponent.handleMouseenter (index.js:1)
at invokeWithErrorHandling (vue.js:1863)
at HTMLLIElement.invoker (vue.js:2188)
at HTMLLIElement.original._wrapper (vue.js:7547)
at VueComponent.handleMouseenter (index.js:1)
at invokeWithErrorHandling (vue.js:1863)
at HTMLLIElement.invoker (vue.js:2188)
at HTMLLIElement.original._wrapper (vue.js:7547)
at VueComponent.handleMouseenter (index.js:1)
at invokeWithErrorHandling (vue.js:1863)
測試代碼
版本:
- vue: v2.6.11
- element-ui: 2.13.0
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!-- 引入樣式 -->
<link rel="stylesheet" rel="external nofollow" >
</head>
<body>
<div id="root">
<el-menu mode="horizontal">
<template v-for="(menu,index) in menus">
<sub-menu v-if="menu.children && menu.children.length" :key="index" :item="menu"></sub-menu>
<el-menu-item v-else :index="menu.path" :key="index">{{ menu.title }}</el-menu-item>
</template>
</el-menu>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 引入組件庫 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script type="text/javascript">
Vue.component('sub-menu', {
props: ['item'],
template: `
<el-submenu :index="item.path">
<template slot="title">
{{item.title}}
</template>
<template v-for="(child,index) in item.children">
<sub-menu v-if="child.children" :item="child" :key="index"></sub-menu>
<el-menu-item v-else :key="index" :index="child.path">
{{child.title}}
</el-menu-item>
</template>
</el-submenu>
`
})
let vm = new Vue({
el: '#root',
data() {
return {
menus: [{
title: '我的工作臺',
path: '2',
children: [{
title: '選項1',
path: '2-1'
},
{
title: '選項2',
path: '2-2',
},
],
},{
title:'后臺管理',
path:'3'
}]
}
},
components: {}
})
</script>
</body>
</html>
錯誤分析
觀察遞歸生成的導(dǎo)航欄代碼及報錯代碼:
handleMouseenter: function(e) {
var t = this
, i = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : this.showTimeout;
if ("ActiveXObject"in window || "focus" !== e.type || e.relatedTarget) {
var n = this.rootMenu
, r = this.disabled;
"click" === n.menuTrigger && "horizontal" === n.mode || !n.collapse && "vertical" === n.mode || r || (this.dispatch("ElSubmenu", "mouse-enter-child"),
clearTimeout(this.timeout),
this.timeout = setTimeout(function() {
t.rootMenu.openMenu(t.index, t.indexPath)
}, i),
this.appendToBody && this.$parent.$el.dispatchEvent(new MouseEvent("mouseenter")));//報錯代碼
}
},
猜測是因為事件冒泡或下沉導(dǎo)致元素重復(fù)派發(fā)和接受mouseenter事件,造成了類似死循環(huán)的狀態(tài),因時間關(guān)系,沒做深究,后面有時間的時候再查下根本原因(如果記得的話…)
當(dāng)鼠標移入到菜單中時,觸發(fā)handleMouseenter方法,但是因為appendToBody為true,所以又派發(fā)了鼠標移入事件,然后又回到了這個方法,由此造成了死循環(huán)。appendToBody是一個計算屬性,那么為什么appendToBody會是true呢?看代碼:
{
name: 'ElSubmenu',
componentName: 'ElSubmenu',
props:{
popperAppendToBody: {
type: Boolean,
default: undefined
}
},
computed:{
appendToBody() {
return this.popperAppendToBody === undefined
? this.isFirstLevel //未顯示指明popperAppendToBody 時,計算這個值
: this.popperAppendToBody;
},
isFirstLevel() {
let isFirstLevel = true;
let parent = this.$parent;
while (parent && parent !== this.rootMenu) {
//計算當(dāng)前是否時第一級菜單。
//看上去是沒問題的,因為代碼里已經(jīng)指明了當(dāng)前的組件名是 componentName: 'ElSubmenu', 但是在調(diào)試中發(fā)現(xiàn),componentName的值是Undefined, 因此不管是在哪一級,最后的結(jié)果都是 isFirstLevel = true
if (['ElSubmenu', 'ElMenuItemGroup'].indexOf(parent.$options.componentName) > -1) {
isFirstLevel = false;
break;
} else {
parent = parent.$parent;
}
}
return isFirstLevel;
}
}
}
至于為什么vue在組件注冊時沒有收集這個參數(shù),還需要從源碼那邊看,午休時間過了,要繼續(xù)擼代碼了…得空了再分析一下…
處理方式
給el-submenu添加一個屬性 :popper-append-to-body=“true false” 顯式的指明appendToBody為false
特別致歉:
此前的處理方式寫錯了,寫的是:popper-append-to-body=“true” 因此即使添加了這個屬性,也依然是報錯的,在此致歉!
到此這篇關(guān)于詳解Element-ui NavMenu子菜單使用遞歸生成時使用報錯的文章就介紹到這了,更多相關(guān)Element-ui NavMenu子菜單遞歸生成內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue引用vee-validate插件表單驗證問題(cdn方式引用)
這篇文章主要介紹了Vue引用vee-validate插件表單驗證問題(cdn方式引用),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
vue?使用addRoutes動態(tài)添加路由及刷新頁面跳轉(zhuǎn)404路由的問題解決方案
我自己使用addRoutes動態(tài)添加的路由頁面,使用router-link標簽可以跳轉(zhuǎn),但是一刷新就會自動跳轉(zhuǎn)到我定義的通配符?*?指向的404路由頁面,這說明沒有找到指定路由才跳到404路由的,這樣的情況如何處理呢,下面小編給大家分享解決方案,一起看看吧2023-10-10

