vue+iview動的ルーティングと権限検証

6726 ワード

githubではvue動的追加ルーティングに関する例が多く,本プロジェクトでは一部のプロジェクトを参照した後,iviewフレームワークに基づいて動的ルーティングの動的追加とメニューリフレッシュを完了した.他の必要な友达を助けるために、実現ロジックを分かち合い、一緒に交流して勉強することを歓迎します.
Githubアドレス
iview-dynamicRouter
目標を達成する.
クライアントは,サービス側からルーティングと権限データを取得した後,プロジェクトのルーティングとメニューリストをリフレッシュし,権限制御を行う.
プロジェクトベース
  • 基礎フレームワーク:iviewコンポーネントライブラリ公式テンプレートプロジェクトiview-adminのtemplate分岐プロジェクト.このプロジェクトはiview-adminの基礎フレームワークコードである.プロジェクトアドレス:iview-admin
  • 権限検証:権限検証はVue+ElementUI手引きバックグラウンド管理ウェブサイトの基本フレームワーク(二)権限制御における実装構想と一部のコードを参照した.

  • インプリメンテーションロジック
    ダイナミックルーティング制御ロード
    一般に、動的ルーティング制御は、すべてのルーティングデータをローカルファイルに格納し、サービス側からユーザの権限情報を取得し、ルーティングジャンプ時に権限判断フックを追加し、ユーザが向かうページが権限リスト内にない場合はジャンプを禁止する2つに分けられる.もう1つは、エラー処理ページ、無権限制御ページなどの基本ルーティングのみをローカルに格納し、権限ルーティングはサーバから取得し、サーバはユーザの権限に応じて対応するルーティングデータを送信し、クライアントはこれらのデータを利用してルーティングの動的生成と追加を行い、本稿では第2の方法を採用する.
    iview-adminプロジェクトでは、ルーティングを3つに分けます.
  • は、Mainコンポーネントのサブページとして示されないページルーティング、例えばlogin、404、403などのエラーページルーティングである.
  • は、Mainコンポーネントのサブページとして示されるが、左側のメニューに表示されないルーティングotherRouter、例えばトップページルーティングである.
  • は、Mainコンポーネントのサブページとして示され、左側のメニューに表示されるルーティングappRouterである.

  • ルーティングデータを取得した後、私たちは主に2つの部分の操作を行い、第1の部分はデータを遍歴し、コンポーネントの非同期ロード方法を利用して、各ルーティングノードに対応するコンポーネントをロードし、その後router.addRoutes(routes)を利用してルーティングリストの動的追加を完了した.第2の部分は、iview-adminフレームワークのページラベルとパン屑ナビゲーションのため、appRouterを巡ってルーティング情報を取得する必要があるため、グローバルアクセスのためにvuexにルーティングデータを格納する必要がある.
    特に、404ページが静的ルーティングである場合、最初にページにアクセスしたとき、動的ルーティングはまだロードされておらず、ルーティングアドレスが見つからないとデフォルトで404エラーページにジャンプし、体験が悪いため、404ルーティングはルーティングルールに書き込まれず、動的ルーティングとともにロードされる.
    主なコードは次のように実装されます.
    データ要求およびルーティングノード生成
    //util.js
    
    //    
    util.initRouter = function (vm) {
        const constRoutes = [];
        const otherRoutes = [];
    
        // 404             
        const otherRouter = [{
            path: '/*',
            name: 'error-404',
            meta: {
                title: '404-     '
            },
            component: 'error-page/404'
        }];
        //       
        util.ajax('menu.json').then(res => {
            var menuData = res.data;
            util.initRouterNode(constRoutes, menuData);
            util.initRouterNode(otherRoutes, otherRouter);
            //        
            vm.$store.commit('updateAppRouter', constRoutes.filter(item => item.children.length > 0));
            //       
            vm.$store.commit('updateDefaultRouter', otherRoutes);
            //       
            vm.$store.commit('updateMenulist', constRoutes.filter(item => item.children.length > 0));
        });
    };
    
    //      
    util.initRouterNode = function (routers, data) {
        for (var item of data) {
            let menu = Object.assign({}, item);
            menu.component = lazyLoading(menu.component);
    
            if (item.children && item.children.length > 0) {
                menu.children = [];
                util.initRouterNode(menu.children, item.children);
            }
            //      
            meta.permission = menu.permission ? menu.permission : null;
            //    
            meta.title = menu.title ? menu.title : null;
            menu.meta = meta;
        }
    };

    ダイナミックロードコンポーネント
    //lazyLoading.js
    
    export default (url) =>()=>import(`@/views/${url}.vue`)

    Storeキャッシュ実装
    //app.js
    
     //          ,    
    updateAppRouter (state, routes) {
        state.routers.push(...routes);
        router.addRoutes(routes);
    },
    
    //         ,     
    updateDefaultRouter (state, routes) {
        router.addRoutes(routes);
    },
    //       ,    
    updateMenulist (state, routes) {
        state.menuList = routes;
    }

    最後はmain.jsで呼び出す
    //main.js
     mounted () {
        //     ,      
        util.initRouter(this);
      }

    アクセス権制御
    動的ルーティングの実現方法と同様に、操作権限制御も一般的に2つに分けられる.1つ目はページ表示時に権限を制御せず、ボタンがすべて表示され、操作開始時に権限判断を行い、ユーザーがその操作権限を持っている場合は通過し、そうでない場合はユーザーに権限がないことを注意し、2つ目はページロード時である.権限判断を行い、権限のない操作は表示されません.本人は更に第2の方法が好きで、このようにユーザーに対して誤導を行うことができなくて、個人はユーザーが見たのが操作できるべきだと思って、さもなくばボタンを押して更に無権限の感じを提示するのはきっととても不快です.
    本プロジェクトの構想の出所は参考博文を参照して、元の博主の具体的な構想は:ルーティング構造のmetaフィールドの中で、ユーザーの操作権限のリストを追加して、それからグローバルコマンドを登録して、ノードが初めてレンダリングする時、そのページに権限があるかどうかを判断して、もし存在して、しかも伝達したパラメータが権限のリストの中でないならば、直接そのノードを削除します.
    主なコードは次のように実装されます.
    ルーティングデータにpermissionフィールドを追加し、権限リストを保存
    //menu.json,        
    [
      {
        "path": "/groupOne",
        "icon": "ios-folder",
        "name": "system_index",
        "title": "groupOne",
        "component": "Main",
        "children": [
          {
            "path": "pageOne",
            "icon": "ios-paper-outline",
            "name": "pageOne",
            "title": "pageOne",
            "component": "group/page1/page1",
            "permission":["del"]
          },
         ...
        ]
      }
    ]

    ルーティングノードの生成時に、permissionフィールドデータがルーティングノードmetaの属性に格納される
    //util.js
    
    //      
    util.initRouterNode = function (routers, data) {
        for (var item of data) {
            ....
            //      
            meta.permission = menu.permission ? menu.permission : null;
            ...
        }
    };

    グローバルコマンドコンポーネントを定義し、ルーティングpermissionの属性値を読み出して権限リストを取得し、権限リストに権限がない場合、ノードを削除する
    //hasPermission.js 
    
    const hasPermission = {
        install (Vue, options) {
            Vue.directive('hasPermission', {
                bind (el, binding, vnode) {
                    let permissionList = vnode.context.$route.meta.permission;
                    if (permissionList && permissionList.length && !permissionList.includes(binding.value)) {
                        el.parentNode.removeChild(el);
                    }
                }
            });
        }
    };
    
    export default hasPermission;

    権限コンポーネントの使用例:

    グローバル登録コンポーネント
    // main.js
    
    import hasPermission from '@/libs/hasPermission.js';
    Vue.use(hasPermission);

    この権限制御方法の利点は,管理構成もページ処理ロジックも比較的簡単で,重複するコード判断やノード処理が多くないことであり,ネット上のいくつかの実装方式を参考に比較した後,個人的にこの方法を推奨することである.
    ページラベルとパンくずのナビゲーション
    私から見れば、ページラベルとパンくずはシステムに花を添えるページ関連コントロールに属し、ページ管理の利便性を高め、iview公式adminプロジェクトでこの2つのコンポーネントを実現した.だからこのプロジェクトでは、それを移植するだけで、コンポーネントの機能を実現し、深く理解していないので、興味のあることはよく研究することができます.
    私に連絡して
    Email:[email protected]
    転載先:https://www.cnblogs.com/zzayne/p/8833516.html