バックエンドの権限に基づいてナビゲーション メニューを動的に生成する 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 グラフィック チュートリアル

推薦する

Vueでブラウザ共有機能を呼び出す方法

序文Vue(発音は /vjuː/、view に似ています)は、ユーザーインターフェイスを構築するため...

RabbitMQ の Docker インストールと設定手順

目次単一マシンの展開オンラインプルミラーを見るRabbitMQを作成して実行するMQコンテナを正常に...

JS の効率的なマジック演算子の概要

JavaScript は現在、毎年新しいバージョンがリリースされており、より便利で効率的な新しい演算...

Web面接におけるJS事前解析と変数プロモーションの違い

目次事前分析とは何ですか?変数と関数の準備の違いvar 変数の繰り返し宣言変数と関数の昇格の優先順位...

ウォーターフォールフローレイアウト(無限読み込み)を実現する js

この記事の例では、ウォーターフォールフローレイアウトを実装するためのjsの具体的なコードを参考までに...

Dockerイメージ内のnoneイメージ操作を削除する

普段はdocker buildコマンドでイメージを生成していますが、コードの更新が頻繁に行われるとn...

Dockerリポジトリの一般的なコマンドの詳細な説明

ログイン dockerログインdocker login コマンドを実行し、ユーザー名、パスワード、メ...

Docker で TLS と CA 認証を有効にする方法

目次1. 証明書を生成する2. リモートを有効にする3. リモート接続3.1 Jenkins接続3....

アバター変更機能を実装するJavaScript

この記事では、アバター変更機能を実装するためのJavaScriptの具体的なコードを参考までに共有し...

5 分で vue-cli3 を使用してプロジェクトを作成する方法を説明します (初心者向けガイド)

目次1. Vue環境を構築する2. Vue スキャフォールディングツール3. プロジェクトを作成する...

SCSS スタイルのコードを 50% 削減する 14 の実践的な経験

序文Sass は CSS3 言語の拡張機能です。Sass を使用すると、より良いスタイルシートをより...

SQL実行ステップの詳細な分析

SQL実行ステップの詳細な分析まず、ステートメントが実行される順序を見てみましょう。 (8)選択する...

CSS で適応型ディバイダーを巧みに実装する N 通りの方法

分割線はウェブページでよく使われるデザインです。例えば、Zhihuのその他の回答をご覧ください。 こ...

Linux CentOS MySQL データベースのインストールと設定のチュートリアル

MySQLデータベースのインストールに関するメモ、みんなで共有a) MySQL ソースインストールパ...

インデックスを使用して MySQL ORDER BY ステートメントを最適化する方法

テーブルの作成とインデックスの作成 テーブルtbl1を作成( id int ユニーク、sname v...