Element-ui NavMenuサブメニューを使用して再帰的に生成する場合のエラーの詳細な説明

Element-ui NavMenuサブメニューを使用して再帰的に生成する場合のエラーの詳細な説明

ナビゲーションバーのサブメニューを再帰的に生成すると、メニューは正常に生成できるが、マウスをホバーすると特定の(mouseenter)イベントが周期的に呼び出され、最終的にエラーが発生する。

処理

注: バージョン 2.13.2 では、この問題を回避するには、サブメニューの属性を popper-append-to-body="false" に設定するだけで済みます。

エラーメッセージは次のとおりです。

キャッチされない RangeError: 最大呼び出しスタック サイズを超えました。
VueComponent.handleMouseenter (index.js:1) で
呼び出し時にエラー処理 (vue.js:1863)
HTMLLIElement.invoker (vue.js:2188) で
HTMLLIElement.original._wrapper (vue.js:7547) で
VueComponent.handleMouseenter (index.js:1) で
呼び出し時にエラー処理 (vue.js:1863)
HTMLLIElement.invoker (vue.js:2188) で
HTMLLIElement.original._wrapper (vue.js:7547) で
VueComponent.handleMouseenter (index.js:1) で
呼び出し時にエラー処理 (vue.js:1863)

テストコード

バージョン:

  • ヴュー: v2.6.11
  • 要素UI: 2.13.0
<!DOCTYPE html>
<html>
 <ヘッド>
  <メタ文字セット="utf-8">
  <タイトル></タイトル>
  <!-- スタイルをインポート -->
  <link rel="スタイルシート" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="外部 nofollow" >
 </head>
 <本文>

  <div id="ルート">
   <el-menu mode="horizo​​ntal">
    <template v-for="(menu,index) メニュー内">
     <サブメニュー v-if="menu.children && menu.children.length" :key="index" :item="メニュー"></サブメニュー>
     <el-menu-item v-else :index="menu.path" :key="index">{{ menu.title }}</el-menu-item>
    </テンプレート>
   </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('サブメニュー', {
    プロパティ: ['アイテム'],
    テンプレート: `
     <el-submenu :index="item.path">
      <テンプレートスロット="タイトル">
       {{item.title}}
      </テンプレート>
      <template v-for="(child,index) in item.children">
       <サブメニュー v-if="child.children" :item="child" :key="index"></サブメニュー>
       <el-menu-item v-else :key="index" :index="child.path">
        {{child.title}}
       </el-menu-item>
      </テンプレート>
     </el-サブメニュー>
    `
   })

   vm = new Vue({
    el: '#root',
    データ() {
     戻る {
      メニュー: [{
       タイトル:「私のワークベンチ」
       パス: '2',
       子供たち: [{
         タイトル: 「オプション 1」
         パス: '2-1'
        },
        {
         タイトル: 「オプション 2」
         パス: '2-2',
        },
       ]、
      },{
       タイトル:「バックグラウンド管理」、
       パス:'3'
      }]
     }
    },
    コンポーネント: {}
   })
  </スクリプト>
 </本文>
</html>

エラー分析

再帰的に生成されたナビゲーション バー コードとエラー コードを確認します。

 handleMouseEnter: 関数(e) {
                    var t = これ
                      , i = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : this.showTimeout;
                    if (ウィンドウ内の "ActiveXObject" || "focus" !== e.type || e.relatedTarget) {
                        var n = this.rootMenu
                          , r = this.disabled;
                        "クリック" === n.menuTrigger && "水平" === n.mode || !n.collapse && "垂直" === n.mode || r || (this.dispatch("ElSubmenu", "mouse-enter-child"),
                        タイムアウトをクリアします(this.timeout)、
                        this.timeout = setTimeout(関数() {
                            t.rootMenu.openMenu(t.index, t.indexPath)
                        }、 私)、
                        this.appendToBody && this.$parent.$el.dispatchEvent(new MouseEvent("mouseenter")));//エラーコード}
                },

これは、イベントのバブリングまたはシンクによって、要素が mouseenter イベントを繰り返しディスパッチおよび受信し、無限ループのような状態になるからだと思います。時間の制約により、詳細には触れませんでした。後で時間があるときに根本的な原因を確認します (覚えていれば...)

マウスがメニュー内に移動すると、handleMouseenter メソッドがトリガーされますが、appendToBody が true であるため、マウスの Enter イベントが再度ディスパッチされ、このメソッドに戻り、無限ループが発生します。 appendToBody は計算プロパティですが、なぜ appendToBody が true なのでしょうか?コードを見てみましょう:

{
 名前: 'ElSubmenu',
    コンポーネント名: 'ElSubmenu',
 小道具:{
  ポッパーをボディに追加: {
         タイプ: ブール値、
         デフォルト: 未定義   
        }
    },
    計算:{
  本文に追加() {
        this.popperAppendToBody === undefined を返します     
          ? this.isFirstLevel //popperAppendToBody が明示的に指定されていない場合は、この値を計算します: this.popperAppendToBody;
      },
      isFirstLevel() {
        isFirstLevel を true にします。
        親を this.$parent とします。
        while (親 && 親 !== this.rootMenu) {
        
        //現在のメニューが最初のレベルであるかどうかを計算します。
        // コードでは現在のコンポーネント名がcomponentName: 'ElSubmenu'であると指定されているため問題ないようです。しかし、デバッグ中にcomponentNameの値がUndefinedであることが判明したため、どのレベルであっても最終結果はisFirstLevel = trueになります。 
          if (['ElSubmenu', 'ElMenuItemGroup'].indexOf(parent.$options.componentName) > -1) {
            isFirstLevel = false;
            壊す;
          } それ以外 {
            親 = 親.$parent;
          }
        }
        isFirstLevel を返します。
      }
 }
}

Vue がコンポーネント登録時にこのパラメータを収集しなかった理由については、まだソースコードを見る必要があります。昼休みも終わり、コーディングを続けなければなりません...時間があるときにもう一度解析します...

処理

el-submenu に属性を追加します: popper-append-to-body="true false" を追加して、appendToBody を明示的に false に指定します。

特別なお詫び:

以前の処理方法は間違って記述されていました。popper-append-to-body="true" と記述されていました。そのため、この属性を追加してもエラーが報告されます。申し訳ありません!

Element-ui NavMenu サブメニューの再帰生成を使用する際のエラーの詳細な説明に関するこの記事はこれで終わりです。Element-ui NavMenu サブメニューの再帰生成に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • vue+elementナビゲーションバーを強調表示するためのソリューション
  • Element-Ui コンポーネント NavMenu のナビゲーション メニューの具体的な使用方法
  • Vueプロジェクトを更新した後にナビゲーションメニューが間違った位置でハイライト表示される問題を解決します
  • elementui で NavMenu ナビゲーション メニューを強調表示する問題を解決する (複数の状況を解決する)

<<:  MySQLデータストレージプロセスパラメータの詳細な例

>>:  VMware Workstation 14 Pro は CentOS 7.0 をインストールします

推薦する

タグ li はブロックレベル要素ですか?

なぜ高さを設定できるのでしょうか。<h1 /> などの要素とは異なり、「セミインライン」...

mysqlはコンマに基づいてデータ行を複数の行に分割します

目次分離効果コマンドラインの説明関与する機能分離効果-- 別居前1,2,3,4 -- 別居後1 2 ...

divとtableの選択と組み合わせ方について簡単に説明します

ページレイアウトは、Web ページを扱い始めた頃からずっと気にかけていたことです。初期のテーブル構造...

バックエンドの権限に基づいてナビゲーション メニューを動的に生成する Vue-router のサンプル コード

目次js の1. グローバルガードを登録する2. Vuex 状態管理グローバルキャッシュルート3. ...

CSS3 でテキストの点滅効果を実現する 3 つの方法 サンプルコード

1. 透明度を変更してテキストを徐々に点滅させると、次のような効果が得られます。 <!DOCT...

docker コンペ応募でよく使われるコマンドのまとめ

アカウントにログイン DOCKER_REGISTRY=registry.cn-hangzhou.al...

Docker 構成コンテナの場所とヒントのまとめ

Docker の使用に関するヒント1. 停止したDockerコンテナをすべてクリーンアップする停止し...

Vue.js $refs 使用例の説明

プロパティやイベントがあるにもかかわらず、JavaScript で子コンポーネントに直接アクセスする...

MySQL サービスを起動できない問題の解決策を含む MySQL 5.7.17 インストール チュートリアル

.net 開発に関しては、Microsoft の SQL Server データベースに精通しており、...

mysql5.7.20 のインストールと設定方法のグラフィック チュートリアル (mac)

MySQL 5.7.20のインストールと設定方法のグラフィックチュートリアルをあなたと共有します1...

Vue で AES.js を使用する詳細な手順

AES暗号化の使用データ転送の暗号化と復号化処理 --- AES.js最初のステップ: vue に ...

MySQL で特定の親行のすべての子行を見つけるソリューション

序文注: テストデータベースのバージョンはMySQL 8.0ですテーブルを作成し、ユーザー scot...

選択タグ内のオプションをクリアする3つの方法

方法1コードをコピーコードは次のとおりです。 document.getElementById(&qu...

Linux で XFS パーティション形式のルート ディレクトリを縮小する方法

目次序文システム環境現在のシステムパーティションレイアウトデータのバックアップレスキューモードに入る...

React Fiberの仕組みの詳細な説明

目次React Fiberとは何ですか?なぜReact Fiberなのか? React Fiberは...