Vue の動的メニュー、動的ルートの読み込みと更新の落とし穴

Vue の動的メニュー、動的ルートの読み込みと更新の落とし穴

必要:

インターフェイスからサブメニュー データを動的に取得します。動的読み込みでは、サブメニュー データが展開されたときにのみ読み込まれる必要があります。更新がサポートされており、ページは正常に表示されます。

アイデア:

最初はアイデアがたくさんあり、少し混乱していました。いろいろ考えました

まず、ルートとメニューはグローバルルートを共有し、データもストアルートを介して送信されます。次に、メニューのレンダリングとルートの読み込みの 2 つのポイントを検討します。ルートとリフレッシュは、ナビゲーションの最初の場所で処理できます。

もう 1 つの場所は、メニュー コンポーネントの展開イベントでメニュー データとルーティングを再生成することです。大体の考え方は似ていて、終わったら忘れてしまいます... リフレッシュ問題はローカルキャッシュで処理する必要があります。 以前はルートビッグデータがキャッシュされていましたが、このローカルストアは文字列のみをキャッシュし、オブジェクトをキャッシュすることはできません。 この場合、メニューは表示されますが、動的ルートは404です。これは、json.parseによって変換されたオブジェクトが実際のルートデータではないため、別途処理する必要があるためです。 コンポーネントは関数オブジェクトです。
それらはすべて落とし穴です...だから私は以前、回り道をして自分の考えをじっくり考えませんでした。

翌日、考えを整理し直して、なぜルート オブジェクト全体をキャッシュする必要があるのか​​考えました。それは愚かなことでしょうか。動的データは 3 レベル メニューの一部にすぎません... 別々に保存しないのはなぜでしょうか。動的メニュー データをローカルに保存し、完全なルート テンプレートを使用し、初期化されたルート オブジェクトを取り出して、メニュー データをループし、children 属性を動的に設定して、新しい完全なルート オブジェクトを生成します。addRoute の方が良いのではないでしょうか。このように考えながら、私は完全なアイデアを整理しました。

[グローバル ルート オブジェクトを定義] => [ナビゲーションの最初の位置を更新し、ルートを初期化してストアにロードして空にする] => [ルーティングとメニューを初期化する] => [メニュー展開イベントで、インターフェイスを要求し、サブメニュー データを取得し、メニュー データを localStore に保存して、ルートを更新する]
繰り返しルーティング、404 の問題の更新、白い画面の更新、非同期処理などの小さな落とし穴もいくつかあります...

レッスン:

問題は確実に解決できる。数日間の苦闘の末、アイデアこそが最も重要だとようやく気づいた。

間違った考えは時間の無駄だ

まずアイデアを考え、完全な実装ルート、最初に何をするか、後で何をするかを考えます。技術的な問題に遭遇した場合は、Baiduにアクセスしてください。

テキストを共有する:

暴力的な郵便番号! ! ! ! ! ! ! ! ! ! ! ! !

グローバルに定義されたストアルートオブジェクトは無視されます

'vue' から Vue をインポートします
'vue-router' から Router をインポートします。
'@/layout' からレイアウトをインポートします

Vue.use(ルーター)

エクスポートconst定数ルート= [{
  パス: '/login',
  名前: 'ログイン',
  コンポーネント: () => import('@/views/login/index'),
  非表示: true、
}, {
  パス: '/404',
  名前: '404',
  コンポーネント: () => import('@/views/error-page/404'),
  非表示: true
}, {
  パス: '/401',
  名前: '401',
  コンポーネント: () => import('@/views/error-page/401'),
  非表示: true
}, {
  パス: '/'、
  コンポーネント: レイアウト、
  リダイレクト: '/dashboard',
  子供たち: [
    {
      パス: 'ダッシュボード',
      コンポーネント: () => import('@/views/dashboard/index'),
      名前: 'ダッシュボード'、
      meta: { title: 'ホームページ', icon: 'ドキュメント' }
    },
    {
      パス: 'xxx',
      コンポーネント: () => import('xxxxx'),
      名前: 'xxx',
      meta: { タイトル: 'XXX', アイコン: 'コンポーネント' },
      子供たち: [
          {
            パス: 'ホスト',
            名前: 'ホスト',
            メタ: { 
              タイトル: 'xxx', 
              キー: 'ホスト'
            }
          },
          {
            パス: 'コントロール',
            名前: 'コントロール',
            常に表示: true、
            メタ: { 
              タイトル: 'xxx', 
              キー: 'コントロール'
            },
            子供たち: []
          },
          {
            パス: 'signal',
            名前: 'シグナル'、
            常に表示: true、
            メタ: { 
              タイトル: 'xxx', 
              キー: 'シグナル'、
            },
            子供たち: [] 
          },
          {
            パス: 'ゲートウェイ',
            名前: 'ゲートウェイ'、
            常に表示: true、
            メタ: { 
              タイトル: 'xxx', 
              キー: 'ゲートウェイ'
            },
            子供たち: []
          } 
      ]
    },
    {
      パス: '会議'、
      名前: 'meting',
      メタ: { タイトル: 'xxx'、アイコン: 'リスト' }
    },
    {
      パス: 'トレース'、
      コンポーネント: () => import('@/views/xxx'),
      名前: 'トレース'、
      meta: { タイトル: 'xxx'、アイコン: 'チャート' }
    }
]
}, 
  {
    パス: '*'、
    リダイレクト: '/404'、
    非表示: true
  }
]

const router = 新しいルーター({
  // モード: 'history'、// サービスサポートが必要
  スクロール動作: () => ({
    年: 0
  })、
  //routes: constantRoutes は初期化を保護します。ここではコメントアウトされています})

//重複ルートの問題を解決する router.$addRoutes = (params) => {
  router.matcher = new Router({ // ルーティングルールをリセットする scrollBehavior: () => ({
      年: 0
    })
  }).マッチャー
  router.addRoutes(params) // ルートを追加}

デフォルトルーターをエクスポートする
// 動的ルートを保護するためにルートを監視する router.beforeEach((to, from, next) => {
  
  定数ルート = store.state.app.routes

  console.error('beforeEach ガードが実行されました')

  //最初のロード更新を処理する if (routes.length === 0) {
     console.error('初回/更新')

     //ルートキャッシュを更新 const cacheRoute = getLocalRouteInfo()
     
     定数ルート値 = asyncRouteDataToRoute(cacheRoute.asyncRouteData、定数ルート)
     
     店
      .dispatch('app/setRoutes', ルート値)

     ルーター.$addRoutes([...routeValue])

     次({
        ...に、
        置き換え: 真
     })
     戻る
   } 

   次()
})
/**
 * 第3レベルのサブメニュールーティングメタデータを更新します */
エクスポートconst updateIPChildRoutes = function(routes, path, children) {
    setRouteArrayChildren(ルート、パス、子) を返します。
}

/**
 * 親メニューに従ってサブメニューをロードします * @param {*} routeKey 
 * @戻り値 
 */
エクスポートconst generateIPChildRoutes = function(routeKey) {
    新しい Promise を返します ((resolve, reject) => {
      if (!routeKey) 戻り値
      
      
      // 定数 start = getDateSeconds(新しい Date())
      // 定数 end = setDateSeconds(new Date(), 15, 'm')
      
      const filterAddr = grafanaAddrs.filter(addr => addr.key === routeKey)[0]
      定数マッチアップ = filterAddr.matchup
  
      定数パラメータ = {
        マッチアップ
      } 
  
      //ルーターを動的に追加
      試す {
        fetchIPInstance(params).then(ipAddrs => {
          定数ipRoutes = []
          ipAddrs.forEach(
            アドレス => {
                const ipInstance = addr.instance.replace(/^(.*):.*$/, "$1")
  
                if(!isIPAddress(ipInstance)) 
                  戻る
  
                const 存在するルート = ipRoutes.find(ip => ip.meta && ip.meta.key === ipInstance)
  
                !existRoute && ipRoutes.push(
                  {
                    パス: ipInstance、
                    名前: ipInstance、
                    メタ: { 
                        タイトル: ipInstance、 
                        キー: ipInstance
                    }
                  }
                )
            }
          )
          解決(ipRoutes)
        })
      } キャッチ(エラー){
        拒否(エラー)
        console.error(`サブメニューの読み込みエラー`)
      }
    })
}
'./tool' から { isArray, setRouteArrayChildren } をインポートします。

// ルート キャッシュ値を設定します。const localRouteKey = "LOCALROUTESET";

/**
 * currentPath: '' //現在アクセスされているルートパス* routeData: [], //保存された完全なルートデータ(メニューの読み込みにのみ使用可能)
 * asyncRouteData: [] //動的ルートデータ(新しいルートを生成するために使用)
 * {
 * parentKey //親キー
 * ルート: [
 * {
            パス: 、
            名前: 、
            メタ: { 
                タイトル: 、 
                鍵: 
            }
        }
 * ]
 * }
 */

エクスポート関数 getLocalRouteInfo() {
  定数データ = localStorage.getItem(localRouteKey);

  データを返します? JSON.parse(data) : {};
}

エクスポート関数setLocalRouteInfo(data) {
  定数 localData = getLocalRouteInfo();

  ローカルストレージ.setItem()
    ローカルルートキー、
    JSON.stringify({
      ...ローカルデータ、
      ...データ、
    })
  );
}

エクスポート関数removeLocalRouteInfo() {
  ローカルストレージからアイテムを削除します。
}

/**
 * ローカルキャッシュをルーティングメタデータに変換* @param {*} constantRoutes ルーティングテンプレート*/
エクスポート関数 asyncRouteDataToRoute(asyncRouteData, constantRoutes) {
   ルートを定数ルートとする
   (isArray(asyncRouteData) && asyncRouteData.length > 0) の場合 {
     非同期ルートデータ.forEach(
        データ => {
          ルート = setRouteArrayChildren(ルート、data.parentKey、data.route)
        }
     )
   }
   帰り道
}
/**
 * ルートの子属性を設定する * @param {*} ルート 
 * @param {*} パス 
 * @param {*} 子 
 * @戻り値 
 */
エクスポートconst setRouteArrayChildren = function(ルート、パス、子) {

  if (!isArray(ルート) || !パス)
     新しい配列を返す()
  
  for (const ルートのルート) {
    if (isArray(route.children)) {
      (route.path === パス && route.children.length === 0)の場合{
        ルート.children.push(...children)
      } それ以外 {
        setRouteArrayChildren(ルート.children, パス, children)
      }
    }
  }

  帰りのルート
}
onExpandMenu(キー、キーパス) {
      console.error(キー、キーパス)

      定数パス = key.substring(key.lastIndexOf('/') + 1)
      console.error(パス)
      

      //監視レベル3のメニュー/ルーティングを動的に生成 const ipAddrKeys = []
      grafanaAddrs.forEach(
        アドレス => {
          if (addr.matchup) {
            ipAddrKeys.push(addr.key)
          }
        }
      )

      if (path && ipAddrKeys.includes(path)) {

         IPChildRoutesを生成する(パス)
         .then(ipAddrs => {
           
          if (isArray(ipAddrs)) {

            //動的ルーティングデータをキャッシュする const localRouteInfo = getLocalRouteInfo()
            const cacheRoutes = localRouteInfo.asyncRouteData || []
            キャッシュルート.push(
                {
                    親キー: パス、
                    ルート:ipアドレス
                }
              )
            ローカルルート情報を設定する({
              非同期ルートデータ: キャッシュルート
            })

            //ルートを更新
            asyncRoutes = store.state.app.routes とします。

            asyncRoutes = updateIPChildRoutes(asyncRoutes、パス、ipAddrs)
            
            店
              .dispatch('app/setRoutes', asyncRoutes)
            
            ルーター.$addRoutes([...asyncRoutes])

          }
         })
      }
    }

その他のコードはコアではないため、投稿されません。

要約する

これで、vue の動的メニュー、動的ルートの読み込み、および更新の落とし穴に関するこの記事は終了です。vue の動的メニューと動的ルートの読み込みに関するその他の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Vue ベースの動的メニュー更新の空白問題の解決
  • Vue で addRoutes を使用して動的ルーティングを実装する例
  • Vue 動的ルーティングを使用してマルチレベルネストされたパンくずリストを実装するためのアイデアと方法
  • vueシリーズにおけるダイナミックルーティングの詳しい解説【オリジナル】
  • Vueルーティング(動的ルーティング、ルーティングネスト)の詳しい説明
  • Vue の動的ルーティング構成とルーティングパラメータの受け渡し方法
  • vue-router の動的ルーティングとは何かを説明します
  • Vue ルーターの基本的な使い方(動的ルーティング、ネストルーティング)の総合分析

<<:  HTML テーブル マークアップ チュートリアル (6): 暗い境界線の色属性 BORDERCOLORDARK

>>:  Elasticsearch を使用する際の一般的な問題の解決策

推薦する

Linuxグループの基礎知識ポイントまとめ

1. Linuxグループの基本紹介Linux では、すべてのユーザーはグループに所属する必要があり、...

MySQL トランザクションの概念と使用法の詳細な説明

目次情事の概念取引の状態取引の役割取引の特徴トランザクション構文トランザクション対応ストレージエンジ...

Nginx 外部ネットワーク アクセス イントラネット サイト構成操作

背景:サイトはフロントエンドとバックエンドから分離されています: vue+springbootフロン...

一定期間の日ごと、時間ごとの統計データを取得するMySQLの詳しい説明

毎日の統計情報を取得するプロジェクトを実行する際、プロジェクト ログを分析する必要があります。要件の...

HTML インライン要素と HTML ブロックレベル要素の概要と違い

ブロックレベル要素の機能: • 常に新しい行から始まり、それ自体で 1 行を占め、後続の要素も新しい...

Vue ミックスインの使用方法とオプションのマージの詳細な説明

目次1. コンポーネントでの使用2. オプションのマージ要約する1. コンポーネントでの使用Mixi...

Centos7 で yum を使用して Ceph 分散ストレージをインストールするチュートリアル

目次序文yumソース、epelソースを設定するCephソースの設定Cephとそのコンポーネントをイン...

Pycharmとsshリモートアクセスサーバーdockerの詳細なチュートリアル

背景: 一部の実験はサーバー上で完了する必要があります。したがって、リモート サーバー上のコードをロ...

高品質なJavaScriptコードの書き方

目次1. 読みやすいコード1. 統一コード形式2. マジックナンバーを削除する3. 単一機能原則2....

nginxプロセスロックの実装の詳細な説明

目次1. nginxプロセスロックの役割2. エントリーレベルのロックの使用3. nginxプロセス...

JavaScript のドキュメント オブジェクト モデル (DOM)

目次1. DOMとは何か2. 要素を選択する3. getElementById() 4. クエリセレ...

VMware+centOS 8 で http プロトコルに基づく Git サービスを構築する方法

目次1. 原因2. デバイス情報3. 準備4. Apacheをインストールする5. gitを設定する...

VueのTodoListケースの詳しい説明

<テンプレート> <div id="ルート"> <...