バックエンド管理システムで作業している場合、通常、メニュー権限制御に関連する問題に遭遇します。もちろん、この問題を解決する方法は、フロントエンド制御とバックエンド制御の 2 つしかありません。弊社の製品のイテレーション速度は比較的速いため、フロントエンドの制御ルーティングからバックエンドの制御ルーティングまでをイテレーションします。以下では、これら 2 つの方法の長所と短所、およびそれぞれの実装方法を紹介します (vue-router API に詳しくない学生は、まず公式 Web サイトにアクセスして API を確認してください)。 まず、プロジェクトの要件について簡単に説明します。下の図に示すように、第 1 レベルのメニューと第 2 レベルのメニューがあり、ログインする人によって異なるメニューが表示されます。 ルーティングのフロントエンド制御のアイデア:すべてのルーティングマッピングテーブルをメンテナンスのためにフロントエンドに持ってきます。つまり、すべてのメニューパスと対応するコンポーネントを router.js に書き込みます。後で、すべてを記述することの欠点について説明します。次に、左側のメニューをコンポーネント (sidebar.vue) に書き込み、このコンポーネントに次のようなデータを書き込み、ログイン時に取得したレベル値を通じてデータ内の固定メニューに hidden を追加しました。すると、フロントエンドは hidden に基づいてメニューを表示しました。 // router.js 疑似コード const Login = r => require.ensure([],()=>r(require('../page/login/Login.vue')),'login'); const Home = r => require.ensure([],()=>r(require('../page/Home.vue')),'home'); const Forbidden = r => require.ensure([],()=>r(require('../page/403.vue')),'forbidden'); const NotFound = r => require.ensure([],()=>r(require('../page/404.vue')),'notfound'); const Dashboard = r => require.ensure([],()=>r(require('../page/dashboard/Dashboard.vue')),'dashboard'); const SplashScreen = r => require.ensure([],()=>r(require('../page/splashScreen/SplashScreen.vue')),'splashScreen'); const AddSplashScreen = r => require.ensure([],()=>r(require('../page/splashScreen/AddSplashScreen.vue')),'addSplashScreen'); 定数ルート = [ { パス: '/'、 リダイレクト: '/login' },{ パス: '/login', コンポーネント: ログイン },{ パス: '/404', コンポーネント: NotFound },{ パス: '/home', コンポーネント: ホーム、 リダイレクト: '/home/splashScreen', 子供たち: [ { パス: '/home/splashScreen', コンポーネント: SplashScreen、 メタ: { タイトル:「国家奉仕 李白」 },{ パス: '/home/addSplashScreen', コンポーネント: AddSplashScreen、 メタ: { タイトル: 国家奉仕 呂布 } } ] } ]; 以下はメニューコンポーネントの擬似コードです。 // サイドバー.vue <テンプレート> <div class="サイドバー"> <el-メニュー> ... </el-menu> </div> </テンプレート> <スクリプト> エクスポートデフォルト{ データ() { 戻る { ルート: [ { インデックス: '1', タイトル:「国家奉仕ジャングル」 アイコン: 'iconfont icon-guanggao', 子供たち: [ { インデックス: 'splashScreen', タイトル: 「李白」 子供たち: [] }, ] }, { インデックス: '2', タイトル:「国家奉仕ミッドフィールダー」、 アイコン:'iconfont icon-tuisongguanli-', } ] } }, メソッド: { レベルを取得する(){ 定数レベル = sessionStorage.getItem('level'); if(レベル === '0'){ this.routes.forEach(関数(値){ if(value.title == "国家奉仕シングル"){ 値.hidden = true; value.children.forEach(関数(値){ if(value.title=="関羽"){ 値.hidden = true; } }) } }) }そうでない場合(レベル === '1'){ this.routes.forEach(関数(値){ 値.hidden = true value.children.forEach(関数(値){ 値.hidden = true; }) }) } } }, 作成された(){ レベルを取得します。 } } </スクリプト> これによりパーミッション機能は実現できますが、2つの問題があります。
ここで、フロントエンドは、バックエンドから返されたレベルを通じてのみルーターを表示/非表示にします。これにより、フロントエンドがルート全体を維持することがより複雑になり、大きなリスクが生じます。 それでは、バックエンド制御ルーティングについて説明します。操作プロセスから始めましょう。ダッシュボードの中間ページを追加しました。このページには、さまざまなレベルの第 1 レベルのルートのみが表示されます。対応する第 1 レベルのルートをクリックすると、対応するページ ページに移動できます。このページにも、対応する第 2 レベルのルートのみが表示されます。 ここでは、「ルートの動的な追加」と「ナビゲーション ガード」と呼ばれる 2 つの新しい概念があります。つまり、フロントエンドの router.js では、ログイン ページや 404 ページなど、誰でもアクセスできるルーティング テーブルのみを記述します。その他のすべてのコンポーネント リソースは新しい components.js ファイルに書き込まれ、バックエンドから返された menuData を使用して components.js 内のキーがマッピングされます。対応するキーがある場合は、addRoutes を通じてルーターに動的に追加されます。ルートを動的に追加する方法は、ナビゲーション ガード beforeEach のフック関数に記述する必要があります。 ナビゲーション ガードとは、次のページにルーティングする前に実行する必要がある操作を意味します。つまり、ログイン後、ダッシュボード ページにジャンプします。このページに入る前に、バックエンドから要求された menuData を再カプセル化し、返されたデータをフロントエンドの components.js の権限に従ってマップする必要があります。最終データを addRoutes を通じてルートにプッシュすると、ダッシュボード ページに入ることができ、ダッシュボード ページを通じて対応するページ ページに入ることができます。つまり、ダッシュボード ページに入る前にすべての権限制御が完了しています。 ここでも小さな最適化ポイントがあります。上記のブラウザ メニュー バーから許可されていないページまたは存在しないページにアクセスする場合、空のページではなく 404 ページに直接アクセスできるように、vue-router の一致する優先順位に従って、ルート 404 と * このページを追加する必要があります。 // components.js すべてのページ リソース const home = () => import('../page/Home.vue'); const splashScreen = () => import('../page/splashScreen/SplashScreen.vue'); const addSplashScreen = () => import('../page/splashScreen/AddSplashScreen.vue'); const editSplashScreen = () => import('../page/splashScreen/EditSplashScreen.vue'); エクスポートデフォルト{ 家、 スプラッシュスクリーン、 スプラッシュスクリーンを追加、 スプラッシュスクリーンの編集、 }; // router.js よく使われるページを書くだけですっきりしませんか? import Vue from 'vue'; 'vue-router' から Router をインポートします。 Vue.use(ルーター); const Login = () => import('../page/login/Login.vue'); const Home = () => import('../page/Home.vue'); const Forbidden = () => import('../page/403.vue'); const Dashboard = () => import('../page/dashboard/Dashboard.vue'); 定数ルート = [ { パス: '/'、 リダイレクト: '/login' },{ パス: '/login', コンポーネント: ログイン },{ パス: '/403', コンポーネント: 禁止 }, { パス: '/dashboard', コンポーネント: ダッシュボード、 }, ]; デフォルトの新しいルーターをエクスポートします({ モード: '履歴'、 ルート: ルート、 ベース: __dirname、 リンクアクティブクラス: 'link-active' }) // main.js 疑似コードは特定の関連ロジックのみを保持します import routeMap from './router/component.js'; const NotFound = () => import('./page/404.vue'); const formatRoutes = function (routes, routeData) { ルートデータの場合 ルートデータ = { 名前: 'ホーム', パス: '/home', // コンポーネントが正常に一致した場合にのみ、特定のページ コンポーネントにアクセスできます: routeMap['home'], 子供たち: []、 }; } ルートの長さ && ルートごとに(ルート => { if(ルート.コンポーネント) { ルートコンポーネント = routeMap[route.component]; ルートデータ.children.push({ パス: route.path、 名前: ルート.インデックス、 コンポーネント: route.component、 メタ: { タイトル: ルート.title, }, }) } ルートの子とルートの子の長さが等しい場合 ルートをフォーマットします(route.children、routeData); } }); routeData を返します。 }; isFetchRemote を true にします。 //フック関数を使用してルートをリダイレクトします router.beforeEach((to, from, next) => { const ユーザー名 = sessionStorage.getItem('ユーザー名'); if(!username && to.path !== '/login'){ 次へ({パス: '/login'}); } そうでない場合 (isFetchRemote && to.path !== '/login') { ajaxPost('/resourceAPI/getMenuData').then(res =>{ res.status === 200 && res.data.errno === 0 の場合 { isFetchRemote = false; const menuData = res.data.result; localStorage.setItem('menudata', JSON.stringify(menuData)); const routeData = formatRoutes(menuData); resourceApp.$router.addRoutes([routeData].concat([ {名前:'404'、パス:'/404'、コンポーネント:見つかりません}, {パス:'*'、リダイレクト:'/404'}])); リソースApp.$router.push({ パス: to.path, クエリ: to.query }); } それ以外 { isFetchRemote = true; } 次(); }) .catch(エラー => { コンソールログ(エラー); }); } それ以外 { 次(); } }); const resourceApp = 新しいVue({ ルーター、 レンダリング: h => h(App) }).$mount('#app'); //menuData リクエストデータ // 第 1 レベル メニューと第 2 レベル メニューの違いは、第 1 レベル メニューにはコンポーネントの値があることです。たとえば、次の SMS 管理には第 1 レベル メニューのみがあります { "エラー番号": 0, "errmsg": "権限が正常に取得されました", "結果": [ { "インデックス": "1", "title": "ジャングルポジション", "アイコン": "アイコンフォントアイコン-guanggao", "子供たち": [ { "インデックス": "スプラッシュスクリーン", "アイコン": "", "タイトル": "ナコルル", 「パス」: 「/home/splashAdverse」、 "コンポーネント": "splashAdverse", "isShow": 真 }, { "インデックス": "スプラッシュスクリーンを追加", "アイコン": "", "タイトル": "李白", 「パス」: 「/home/addAdverse」、 "コンポーネント": "addAdverse", "isShow": 偽 }, ] }, { "インデックス": "メッセージ", "title": "国家奉仕最高位", "アイコン": "アイコンフォントアイコン-duanxinguanli", "パス": "/home/message", "コンポーネント": "メッセージ", "子供たち": [ { "インデックス": "メッセージを追加", "title": "中国最高の関羽", "アイコン": "", "パス": "/home/addMessage", "コンポーネント": "メッセージを追加", "isShow": 偽 } ] } ] } サイドバーとダッシュボードの 2 つのコンポーネントは、セッションを通じてバックエンドのメニューデータを取得するだけで済みます。 // ダッシュボード疑似コード <テンプレート> <div class="nav_list"> <div class="nav_list_item" v-for="navList 内のアイテム" @click="goPage(item)"> <i :class="item.icon"></i> <h2>{{item.title}}</h2> </div> </div> </テンプレート> <スクリプト> 作成された(){ 定数 routeArr = JSON.parse(localStorage.getItem('menudata')); this.navList = ルートArr; }, メソッド: { ページへ移動(アイテム){ // 1レベルメニューのみ if (item.component) { this.$router.push(item.path); }それ以外{ // セカンダリメニューのデータ構造には子のパスのみが含まれます this.$router.push(item.children[0]['path']); } } } </スクリプト> // サイドバー疑似コード <script> エクスポートデフォルト{ データ() { 戻る { ルート: [], } }, メソッド: { バウンサー(arr){ arr.filter(function(val){ を返す 戻り値 !(!val || val === ""); }); } }, 作成された(){ const menuData = JSON.parse(localStorage.getItem('menudata')); // 現在のルーターのパスに対応するルーティング配列全体をマップします。letroutes = menuData.map((item)=>{ // ルーティングは1レベルのみ if (item.component && item.path == this.$route.path) { コンソール.log(アイテム) 返品商品; }それ以外{ if(item.children[0]['path'] == this.$route.path){ コンソール.log(アイテム) 返品商品; } } }) // 配列内の未定義、null、その他の空の値と false の値を削除します。 this.routes = this.bouncer(routes); } } </スクリプト> このように権限を制御することで、ブラウザ コンソールでセッションのレベルを変更したり、ブラウザのナビゲーション バーでパスを変更したりすると、ナビゲーション ガードに戻る、つまり、menuData を再取得する要求を送信します。ルートを追加した後、この値が一致しない場合は、404 に戻ります。もちろん、レベルを変更しても、権限の変更の制御は実現されません。これは、以前のフロントエンド制御ルートではなく、ルートを動的に取得するためです。 これで、Vue でメニュー権限制御を実装するためのサンプルコードに関するこの記事は終了です。Vue メニュー権限に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: DockerプライベートライブラリHarborのアーキテクチャとコンポーネントの説明
>>: MySQL は正常に起動するがポートをリッスンしない場合の解決策
目次1. nodejsをダウンロードする2. ダブルクリックしてインストール3. グローバル npm...
データ URI スキームを使用すると、HTML、CSS、Javascript などで使用できるインラ...
ファイルの保存とアクセスを容易にするために、FTPサービスが特別に構築されています。 FTP サーバ...
nginx の概要nginx は、無料のオープンソースの高性能 HTTP サーバーおよびリバース プ...
1. スタートアップメニューでは、カーソルを最初の行に移動します - eを押します 2. UTF-8...
Docker Toolbox は、Windows 10 Professional より前のバージョン...
序文: Vueプロジェクトで透かし効果を使用するには、コンテナを指定できます効果画像: 1. コンテ...
目次概要本日正午、開発およびテスト環境の MySQL サービスで接続数が多すぎるというエラーが報告さ...
この記事の例では、コンピュータカメラを呼び出して写真機能を実現するためのvueの具体的なコードを参考...
目次1.ソケットを作成する2. ソケットをバインドする3. 聞き手を作る。聞く4. 接続が受け入れら...
導入Memcached は分散キャッシュ システムです。Memcached には認証とセキュリティ制...
MacにMySQLデータベースをインストールし、環境変数を設定する手順を参考までに記録します。具体的...
1. HTMLタグは常に閉じる前のページのソース コードでは、次のような記述がよく見られます。 &l...
CSSを使用してブラウザのスクロールバーのスタイルを変更する ::-webkit-スクロールバー{ ...
最近、何人かの友人から、仮想マシンに CentOS をインストールした後、ifconfig コマンド...