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

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

js の

  • vue-ルーター
  • ヴュークス

1. グローバルガードを登録する

コアロジック
1. トークン認証(バックエンド) => トークンが無効な場合はログインページに戻る
2. ユーザー権限を取得する
3. 権限を確認し、ルーティングメニューを動的に追加する

router.beforeResolve はグローバル ガードを登録します。 router.beforeEach と似ていますが、ナビゲーションが確認される前、およびすべてのコンポーネント ガードと非同期ルート コンポーネントが解決された後に、解決ガードが呼び出される点が異なります。

router.beforeResolve(async (to, from, next) => {
  hasToken = store.getters['User/accessToken'] とします。
  if (!settings.loginInterception) hasToken = true
  (トークンを持っている場合){
    to.path === '/auth/sign-in'の場合{
      次へ({ パス: '/' })
    } それ以外 {
      定数hasPermissions =
        store.getters['ユーザー/権限'] &&
        store.getters['ユーザー/権限'].length > 0
      権限がある場合
        次()
      } それ以外 {
        試す {
          許可を与える
          定数ログインインターセプションの場合{
            // settings.js loginInterception が false の場合、仮想権限を作成します。await store.dispatch('User/setPermissions', ['admin'])
            権限 = ['管理者']
          } それ以外 {
            権限 = store.dispatch('User/getUserInfo') を待機します
          }
          accessRoutes = [] とします
          accessRoutes = store.dispatch('Routes/setRoutes', 権限) を待機します
          // ルートを追加する router.addRoutes(accessRoutes)
          次({ ...to, 置き換え: true })
        } キャッチ {
          store.dispatch('User/resetAccessToken') を待機します。
        }
      }
    }
  } それ以外 {
    (settings.routesWhiteList.indexOf(to.path) !== -1) の場合 {
      次()
    } それ以外 {
      次へ('/auth/sign-in')
    }
  }
  document.title = getPageTitle(to.meta.title)
})

settings.js グローバル設定

エクスポートデフォルト{
  // ログインインターセプションを有効にするかどうか loginInterception: true,
  // トークン検証に合格しないルートroutesWhiteList: ['/auth/sign-in', '/auth/register', '/401', '/404'],
}

2. Vuex 状態管理グローバルキャッシュルート

  • 状態: データのグローバルストレージ
  • ゲッター: 計算されたものと理解でき、データを計算する
  • 突然変異: データへの同期的な変更
  • アクション: データへの非同期変更 (非同期操作の実装)
  • モジュール: ストアをモジュールに分割する
/**
 * @著者 アラン
 * @description ルーティングインターセプトステータス管理*/
'@/router' から { asyncRoutes, constantRoutes } をインポートします。
'@/Utils/handleRoutes' から { filterAsyncRoutes } をインポートします。

定数状態 = () => ({
  ルート: [],
  部分ルート: []
})
const ゲッター = {
  ルート: (状態) => state.routes、
  部分ルート: (状態) => state.partialRoutes
}
const 変異 = {
  setRoutes (状態、ルート) {
    state.routes = constantRoutes.concat(routes)
  },

  setPartialRoutes (状態、ルート) {
    state.partialRoutes = constantRoutes.concat(ルート)
  }
}
定数アクション = {
  非同期setRoutes({コミット}、権限){
    const finallyAsyncRoutes = filterAsyncRoutesを待機します(
      [...asyncRoutes]、
      権限
    )
    コミット('setRoutes'、finallyAsyncRoutes)
    finallyAsyncRoutes を返す
  },
  setPartialRoutes ({ commit }, accessRoutes) {
    コミット('setPartialRoutes'、アクセスルート)
    アクセスルートを返す
  }
}
エクスポート デフォルト { namespaced: true, state, getters, mutations, actions }

3. ルーティング傍受

/**
 * @著者 アラン
 * @description 現在のルートに権限が含まれているかどうかを判定します* @param 権限
 * @param ルート
 * @returns {ブール値|*}
 */
エクスポート関数hasPermission(権限、ルート){
  ルートメタの場合、ルートメタのパーミッションは次のようになります。
    権限を返します。(ロール) => route.meta.permissions.includes(ロール))
  } それ以外 {
    真を返す
  }
}

/**
 * @著者 アラン
 * @description 権限配列に基づいてルートをインターセプトします * @param ルート
 * @param 権限
 * @returns {[]}
 */
エクスポート関数 filterAsyncRoutes (ルート、権限) {
  const finallyRoutes = []
  ルート.forEach((ルート) => {
    const アイテム = { ...ルート }
    if (hasPermission(権限, アイテム)) {
      if (item.children) {
        item.children = filterAsyncRoutes(item.children, 権限)
      }
      最後にルートをプッシュします(アイテム)
    }
  })
  finallyRoutes を返す
}

4. ルーティングメニュー

/*
* @著者 アラン
* @description パブリックルーティング */
エクスポートconst constantRoutes = [
  {
    パス: '/auth',
    名前: 'auth1',
    コンポーネント: AuthLayout、
    子: authChildRoutes('auth1'),
    hidden: true // メニューを非表示にする},
  {
    パス: '/'、
    名前: 'ダッシュボード'、
    コンポーネント: VerticleLayout、
    メタ: {
      タイトル:「ダッシュボード」
      名前: 'sidebar.dashboard',
      is_heading: 偽、
      is_active: 偽、
      リンク: ''、
      クラス名: ''、
      is_icon_class: true、
      アイコン: 'ri-home-4-line',
      権限: ['admin']
    },
    子: childRoutes('dashboard')
  }
]

/*
* @著者 アラン
* @description 非同期ルーティング */
エクスポートconst asyncRoutes = [
  {
    パス: '/menu-design',
    名前: '水平ダッシュボード'、
    コンポーネント: Horizo​​ntalLayout、
    メタ: {
      タイトル:「メニューデザイン」
      名前: 'sidebar.MenuDesign',
      is_heading: 偽、
      is_active: 偽、
      リンク: ''、
      クラス名: ''、
      is_icon_class: true、
      アイコン: 'ri-menu-3-line',
      権限: ['admin']
    },
    子: 水平ルート('ダッシュボード')
  }, {
    パス: '/core',
    名前: 'コア',
    コンポーネント: VerticleLayout、
    メタ: {
      タイトル: 「UI要素」、
      名前: 'sidebar.uiElements',
      is_heading: 偽、
      is_active: 偽、
      クラス名: ''、
      リンク: ''、
      is_icon_class: true、
      アイコン: 'ri-pencil-ruler-line',
      権限: ['admin']
    },
    子: coreChildRoute('core')
  }
]

5. 再帰メニュー Vue コンポーネント

<テンプレート>
  <b-collapse タグ="ul" :class="className" :visible="open" :id="idName" :accordion="accordianName">
    <li v-for="(item,index) in items" :key="index" :class=" !hideListMenuTitle? 'p-0' : item.meta.is_heading ? 'iq-menu-title' :activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''">
      <テンプレート v-if="!item.hidden">
        <i v-if="item.meta.is_heading && hideListMenuTitle" class="ri-subtract-line" />
        <span v-if="item.meta.is_heading && hideListMenuTitle">{{ $t(item.meta.name) }}</span>
        <router-link :to="item.meta.link" v-if="!item.is_heading" :class="`iq-waves-effect ${activeLink(item) && item.children ? 'active' : activeLink(item) ? 'active' : ''}`" vb-toggle="item.meta.name">
          <i :class="item.meta.icon" v-if="item.meta.is_icon_class"/>
          <テンプレート v-else v-html="item.meta.icon">
          </テンプレート>
          <span>{{ $t(item.meta.name) }}</span>
          <i v-if="item.children" class="ri-arrow-right-s-line iq-arrow-right" />
          <small v-html="item.meta.append" v-if="hideListMenuTitle" :class="item.meta.append_class" />
        </ルーターリンク>
        <リスト v-if="item.children" :items="item.children" :sidebarGroupTitle="hideListMenuTitle" :open="item.meta.link.name !== '' && activeLink(item) && item.children ? true : !!(item.meta.link.name !== '' && activeLink(item))" :idName="item.meta.name" :accordianName="`sidebar-accordion-${item.meta.class_name}`" :className="`iq-submenu ${item.meta.class_name}`" />
      </テンプレート>
    </li>
  </b-collapse>
</テンプレート>
<スクリプト>
import List from './CollapseMenu' // 自己コンポーネント import { core } from '../../../config/pluginInit'
エクスポートデフォルト{
  名前: 'リスト',
  小道具: {
    アイテム: 配列、
    クラス名: { タイプ: 文字列、デフォルト: 'iq-menu' },
    open: { 型: ブール値、デフォルト: false },
    idName: { タイプ: 文字列、デフォルト: 'サイドバー' },
    accordianName: { タイプ: 文字列、デフォルト: 'sidebar' },
    sidebarGroupTitle: { タイプ: ブール値、デフォルト: true }
  },
  コンポーネント:
    リスト
  },
  計算: {
    リストメニュータイトルを非表示にする() {
      this.sidebarGroupTitle を返す
    }
  },
  マウントされた(){
  },
  メソッド: {
    アクティブリンク (アイテム) {
      core.getActiveLink(item, this.$route.name) を返します
    }
  }
}
</スクリプト>

これで、バックエンドの権限に基づいてナビゲーション メニューを動的に生成する vue-router のサンプル コードに関するこの記事は終了です。vue-router の権限ナビゲーション メニューに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue-element-adminフレームワークを使用して、バックエンドからメニュー機能を動的に取得します。
  • Vue のルーティングの動的追加とメニューメソッドの生成の例
  • Vue サイドバーでサブメニューを動的に生成する方法
  • Vueはどのようにしてバックグラウンドからデータを取得して動的なメニューリストを生成するのか

<<:  MySQL データ型の最適化の原則

>>:  Tomcat サーバーの設定と Web プロジェクトの公開に関する IDEA グラフィック チュートリアル

推薦する

HTML でのアンカーポイントの適用

アンカーポイントの設定<a name="トップ"></a>...

Vue フロントエンド開発における階層的にネストされたコンポーネント間の通信の詳細な説明

目次序文例まとめ序文Vue の親子コンポーネントは、props を通じて親コンポーネントの値を子コン...

Docker で Nginx イメージ サーバーを構築する方法

序文一般的な開発では、画像をディレクトリにアップロードし、ディレクトリとファイル名を連結してデータベ...

Angular CDK を使用してサービスポップアップトーストコンポーネント機能を実装する

目次1. 環境設備2. ToastコンポーネントとToastServiceを作成する2.1 Toas...

Linux インストール MySQL チュートリアル (バイナリ配布)

このチュートリアルでは、LinuxにMySQLをインストールする詳細な手順を参考までに紹介します。具...

JavaScript における clientWidth、offsetWidth、scrollWidth の違い

1. コンセプトこれらはすべて Element の属性であり、要素の幅を示します。 Element....

Window.nameはクロスドメインデータ転送の問題を解決します

<br />原文: http://research.microsoft.com/~hel...

Dockerでのpython3.8イメージのインストールについて

Docker Hub公式サイト1. Pythonミラーを検索するdocker 検索 python 2...

Docker Compose を使用して Confluence を構築するチュートリアル

この記事は「Attribution 4.0 International (CC BY 4.0)」ライ...

CSS オーバーフローラップの新しいプロパティ値をどこでも使用

1.まず、overflow-wrap属性を理解する CSS のoverflow-wrapプロパティは...

Vue3.0はチェックボックスコンポーネントのカプセル化を実装します

この記事では、チェックボックスコンポーネントのカプセル化を実装するためのvue3.0の具体的なコード...

Docker 入門インストールチュートリアル (初心者版)

ドクター紹介: Docker はコンテナ関連の技術です。簡単に言うと、さまざまなソフトウェアを実行で...

Vue Element フロントエンドアプリケーション開発 従来の Element インターフェースコンポーネント

目次1. リストインターフェースとその他のモジュールの表示処理2. 従来のインターフェースコンポーネ...

負荷分散と動的および静的分離操作を実現するDocker NginxコンテナとTomcatコンテナ

Tomcat8 イメージをダウンロード [root@localhost ~]# docker sea...

一般的でない js 演算演算子の概要

目次2. カンマ演算子3. JavaScript Null 結合演算子 (??) 4. JavaSc...