詳解Element-ui NavMenu子菜單使用遞歸生成時(shí)使用報(bào)錯(cuò)
當(dāng)采用遞歸方式生成導(dǎo)航欄的子菜單時(shí),菜單可以正常生成,但是當(dāng)鼠標(biāo)hover時(shí),會(huì)出現(xiàn)循環(huán)調(diào)用某個(gè)(mouseenter)事件,導(dǎo)致最后報(bào)錯(cuò)
處理方式
注:2.13.2 版本,只需對(duì)子菜單設(shè)置屬性 :popper-append-to-body="false" 就不會(huì)出現(xiàn)這個(gè)問(wèn)題了
報(bào)錯(cuò)信息如下:
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)
測(cè)試代碼
版本:
- 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> <!-- 引入組件庫(kù) --> <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: '我的工作臺(tái)', path: '2', children: [{ title: '選項(xiàng)1', path: '2-1' }, { title: '選項(xiàng)2', path: '2-2', }, ], },{ title:'后臺(tái)管理', path:'3' }] } }, components: {} }) </script> </body> </html>
錯(cuò)誤分析
觀察遞歸生成的導(dǎo)航欄代碼及報(bào)錯(cuò)代碼:
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")));//報(bào)錯(cuò)代碼 } },
猜測(cè)是因?yàn)槭录芭莼蛳鲁翆?dǎo)致元素重復(fù)派發(fā)和接受mouseenter事件,造成了類似死循環(huán)的狀態(tài),因時(shí)間關(guān)系,沒(méi)做深究,后面有時(shí)間的時(shí)候再查下根本原因(如果記得的話…)
當(dāng)鼠標(biāo)移入到菜單中時(shí),觸發(fā)handleMouseenter方法,但是因?yàn)閍ppendToBody為true,所以又派發(fā)了鼠標(biāo)移入事件,然后又回到了這個(gè)方法,由此造成了死循環(huán)。appendToBody是一個(gè)計(jì)算屬性,那么為什么appendToBody會(huì)是true呢?看代碼:
{ name: 'ElSubmenu', componentName: 'ElSubmenu', props:{ popperAppendToBody: { type: Boolean, default: undefined } }, computed:{ appendToBody() { return this.popperAppendToBody === undefined ? this.isFirstLevel //未顯示指明popperAppendToBody 時(shí),計(jì)算這個(gè)值 : this.popperAppendToBody; }, isFirstLevel() { let isFirstLevel = true; let parent = this.$parent; while (parent && parent !== this.rootMenu) { //計(jì)算當(dāng)前是否時(shí)第一級(jí)菜單。 //看上去是沒(méi)問(wèn)題的,因?yàn)榇a里已經(jīng)指明了當(dāng)前的組件名是 componentName: 'ElSubmenu', 但是在調(diào)試中發(fā)現(xiàn),componentName的值是Undefined, 因此不管是在哪一級(jí),最后的結(jié)果都是 isFirstLevel = true if (['ElSubmenu', 'ElMenuItemGroup'].indexOf(parent.$options.componentName) > -1) { isFirstLevel = false; break; } else { parent = parent.$parent; } } return isFirstLevel; } } }
至于為什么vue在組件注冊(cè)時(shí)沒(méi)有收集這個(gè)參數(shù),還需要從源碼那邊看,午休時(shí)間過(guò)了,要繼續(xù)擼代碼了…得空了再分析一下…
處理方式
給el-submenu添加一個(gè)屬性 :popper-append-to-body=“true false” 顯式的指明appendToBody為false
特別致歉:
此前的處理方式寫錯(cuò)了,寫的是:popper-append-to-body=“true” 因此即使添加了這個(gè)屬性,也依然是報(bào)錯(cuò)的,在此致歉!
到此這篇關(guān)于詳解Element-ui NavMenu子菜單使用遞歸生成時(shí)使用報(bào)錯(cuò)的文章就介紹到這了,更多相關(guān)Element-ui NavMenu子菜單遞歸生成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue動(dòng)態(tài)路由刷新失效以及404頁(yè)面處理辦法
作為一個(gè)前端新手,項(xiàng)目中遇到權(quán)限處理時(shí),通常會(huì)采用動(dòng)態(tài)添加路由的方法來(lái)實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于vue動(dòng)態(tài)路由刷新失效以及404頁(yè)面處理辦法的相關(guān)資料,需要的朋友可以參考下2023-11-11Vue引用vee-validate插件表單驗(yàn)證問(wèn)題(cdn方式引用)
這篇文章主要介紹了Vue引用vee-validate插件表單驗(yàn)證問(wèn)題(cdn方式引用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12vue單頁(yè)應(yīng)用中如何使用jquery的方法示例
最近在工作中遇到的一個(gè)需求,需要在vue-cli建立的應(yīng)用中引入jquery的方式,通過(guò)查找相關(guān)的資料最終解決了,所以這篇文章主要給大家介紹了關(guān)于在vue單頁(yè)應(yīng)用中如何使用jquery的方法示例,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-07-07實(shí)時(shí)通信Socket?io的使用示例詳解
這篇文章主要為大家介紹了實(shí)時(shí)通信Socket?io的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11vue?使用addRoutes動(dòng)態(tài)添加路由及刷新頁(yè)面跳轉(zhuǎn)404路由的問(wèn)題解決方案
我自己使用addRoutes動(dòng)態(tài)添加的路由頁(yè)面,使用router-link標(biāo)簽可以跳轉(zhuǎn),但是一刷新就會(huì)自動(dòng)跳轉(zhuǎn)到我定義的通配符?*?指向的404路由頁(yè)面,這說(shuō)明沒(méi)有找到指定路由才跳到404路由的,這樣的情況如何處理呢,下面小編給大家分享解決方案,一起看看吧2023-10-10