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 をインストールします

推薦する

Node.js の非同期イテレータの詳細な説明

目次序文非同期イテレータとは何ですか?非同期イテレータストリームとしてページング機能を備えたAPIの...

CSSスタイルは、テキストが長すぎる場合に省略記号を表示する問題を解決します

1. CSSスタイルは、テキストが長すぎる場合に省略記号を表示する問題を解決します1. 一般的なスタ...

Dockerを使用してLaravelおよびVueプロジェクトの開発環境を構築する詳細な説明

この記事では、Docker で構築された Laravel および Vue プロジェクトの開発環境を紹...

MySQLデータベースの共通操作スキルのまとめ

この記事では、MySQL データベースの一般的な操作テクニックをまとめます。ご参考までに、詳細は以下...

mysql ローカルログインでポート番号を使用してログインできない問題の解決策

最近、Linux を使用してローカルにログインしていたところ、正常にログインできず、次のエラー メッ...

MySQL Community Server 5.7.16 のグリーン バージョンをインストールしてリモート ログインを実装する方法

1. MySQL Community Server 5.7.16をダウンロードしてインストールします...

Dockerがプライベート倉庫Harborを構築する手順

港Harborは、エンタープライズレベルのプライベートDockerイメージリポジトリを構築するための...

Win10 での MySQL 8.0.16 のインストールと設定のチュートリアル

1. MySQL 8.0.16を解凍する次の図に示すように、解凍後にdadaフォルダとmy.ini構...

Docker-compose は Docker プライベート ウェアハウスのステップを迅速に構築します

docker-compose.ymlを作成し、次の内容を入力します。 バージョン: '3&#...

Mysql の一般的なベンチマーク コマンドの概要

mysqlslap共通パラメータの説明–auto-generate-sql システムはテスト用のSQ...

MySql のグループ化と各グループからランダムに 1 つのデータを取得する

アイデア: 最初にランダムに並べ替えてからグループ化します。 1. テーブルを作成します。 テーブル...

HTTP ヘッダー情報の解釈と分析 (詳細概要)

HTTP ヘッダーの説明1. Accept: Web サーバーに受け入れるメディア タイプを通知しま...

Python MySQL データベース テーブルの変更とクエリ

Python は MySQL に接続してデータベース テーブルを変更およびクエリします。 pytho...

Windows Server 2016 で Flash を有効にする方法

最近、VMware Horizo​​n を導入してテストしましたが、そのコンソールにはデフォルトで ...