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

推薦する

CocosCreator でレイヤー管理に常駐ノードを使用する方法

CocosCreator バージョン: 2.3.4ほとんどのゲームにはレイヤー管理機能があり、例えば...

JavaScript プリミティブデータ型シンボルの詳細な説明

目次導入説明名前の競合私有財産要約する導入シンボル変数を作成する最も簡単な方法は、Symbol() ...

Nginx 急ぎ購入 電流制限構成 実装分析

ビジネス上のニーズにより、急ぎの購入が発生することが多いため、ロード バランシング フロント エンド...

MySQL 5.7 クラスタ構成手順

目次1. サーバーAのmy.cnfファイルを変更する2. サーバーBのmy.cnfファイルを変更する...

CSS3で実装されたグラデーションスライド効果

成果を達成する コードhtml <div class="css-slideshow&...

MySQL CHARとVARCHARの選択方法

目次VARCHAR 型と CHAR 型結論: VARCHAR 型と CHAR 型VARCHAR と ...

DOCTYPE要素詳細説明完全版

1. 概要この記事では、DOCTYPE要素を体系的に説明します。同時に、多くの情報を調べました。イン...

Mysql での結合操作

結合の種類1. 内部結合: 結合関係を持つ 2 つのテーブル内のフィールドは、結合関係を満たすレコー...

Nginx を使用して IP アドレスが悪意を持って解決されるのを防ぐ方法

Nginxを使用する目的Alibaba Cloud ECS クラウド サーバーを使用して、まずは著者...

Vueのウェブページスクリーンショット機能の詳しい説明

最近、プロジェクトで写真をアップロードする要件があるのですが、顧客がアップロードする写真のサイズがま...

Web ページでの Unicode 文字の使用の概要 (&#、\u など)

初期のコンピュータでは ASCII 文字しか使用できませんでしたが、コンピュータのアプリケーションの...

MySQL で期限切れのデータレコードを定期的に削除する簡単な方法

1. MySQL に接続してログインしたら、まず MySQL でイベント機能が有効になっているかどう...

CSS の overflow: hidden の使い方 (オーバーフローの非表示とフロートのクリア)

オーバーフロー非表示指定された高さを超えるテキストや画像情報を非表示にすることを意味します。 <...

Linux自動ログイン例の説明

インターネット上には、expect を使用して自動ログインを実現するスクリプトが多数存在しますが、明...