vue-routerはルート権限の実現を制御します。


注意:vue-routerは、フロントエンドのルーティング権限を完全に制御できません。
1、考え方を実現する
vue-router実例関数addRoutesを使用して、ルーティング規則を動的に追加し、多くの無駄話をせずに直接的に思考ガイド図を追加します。

2、実現ステップ
2.1、ルートマッチング判断

// src/router.js

import Vue from 'vue';
import Store from '@/store';
import Router from 'vue-router';
import Cookie from 'js-cookie';
const routers = new Router({
  base : "/test",
  //           、404、401 
  routes : [{
    path : "/404",
    // ...
  },{
    path : "/401",
    // ...
  }]
})
// ...      
routes.beforeEach((to, from, next) => {
  const { meta, matched, path } = to;
  let isMatched = matched && matched.length > 0; //       
  if(isMatched){
  
  }else{
  
  }
})

vue-routerフロントガードbeforeEachのパラメータtoにより、マッチング結果を簡単に実現します。
2.2、登録アクセス制御
実際の開発においては、アクセスが登録されているかどうかとログインが必要かどうかが常に存在するので、tokenとルーティング設定meta情報の中でisAuthフィールドを定義することで区別することができる。

// ...        

const openRouters = [];
const authRouters = [{
  path : "order/list",
  // ...
  meta : {
    //       (      false  true       )
    isAuth : true
  }
}];

routes.beforeEach((to, from, next) => {
  const { meta, matched, path } = to;
  let isMatched = matched && matched.length > 0; //       
  let isLogin = Cookie.get("token") || null;
  let { isAuth } = (meta || {});
  if(isMatched){
    //      
    if(isAuth){
      //       
      if(isLogin){
        //      
        next(); //       
      }else{
        //      
        next("/login"); //     
      }
    }else{
      //        
      next(); //       
    }
  }else{
    //       
    if(isLogin){
      //      
      
    }else{
      //      
      next("/login"); //     
    }
  }
})

2.3、ルーティングルールを動的に追加する
ルーティング・ルールを動的に追加するためには、vue−routerの例示的な方法router.addRoutes(routes:Aray)が必要である。
問題が来ました。どうやって動的に追加するルートルールを取得できますか?
2.4、ルートルールマッチング関数の構築
バックグラウンドで取得したルーティング権限のリストがこのような場合:

[{
 resourceUrl : "/order/list",
 childMenu : ...
}]
ユーザー権限とルーティングが一致するかどうかを比較するためには、権限ルーティング配列を抽出する必要があります。

//                url
export function getAuthRouters(authMenu) {
  let authRouters = [];
  (authMenu || []).forEach((item) => {
    const { resourceUrl, childMenu } = item;
    resourceUrl && authRouters.push(resourceUrl);
    if (childMenu && childMenu.length > 0) {
      //       
      authRouters = [...authRouters, ...getAuthRouters(childMenu)];
    }
  });
  return authRouters;
}
get AuthRouters関数を通じて、すべてのユーザーのルート権限を取得しました。次はどのようにvue-routerルートとマッチングしますか?
これは(私がここで使っているのはRBACモデルです)システムの構成権限に関連します。vue-routerルーティングルールは、権限設定と一致している必要があります。したがって、再帰的に動的に接続することによって、Vue-routerルーティングルールとユーザーが持つルーティング権限とを比較することができる。一致する場合はルートを保持します。その後、フィルタリングされたvue-routerルート規則の設定を取得します。最後に、例示的な方法によって、ルーティングルールが追加される。具体的な実現コードは以下の通りです。

// src/utils/index.js
const { pathToRegexp } = require('path-to-regexp');

export function createAuthRouters(authRouters) {
  const isAuthUrl = (url) => {
    return (authRouters || []).some((cUrl) => {
      return pathToRegexp(url).toString() === pathToRegexp(cUrl).toString();
    });
  };
  return function createRouters(routers, upperPath) {
    let nRouters = [];
    (routers || []).forEach((item) => {
      const { children, path, name } = item;
      let isMatched = false,
        nItem = { ...item },
        fullPath = `${upperPath || ''}/${path}`.replace(/\/{2,}/, '/'),
        nChildren = null;
      children && (nChildren = createRouters(children, fullPath));
      // 1.      
      if (isAuthUrl(fullPath)) {
        isMatched = true;
      }
      // 2.       
      if (nChildren && nChildren.length > 0) {
        nItem.children = nChildren;
        isMatched = true;
      }
      //     (       )
      if(name === "home"){
        isMatched = true;
      }
      // nItem
      isMatched && nRouters.push(nItem);
    });
    return nRouters;
  };
}
注意すべきなのは、createAuthRouters方法が変数isMatchによって保持されるかどうかを制御しています。変数によって決定されるのは、入れ子ルートにおいて親ルートが一致しないかもしれませんが、子ルートが適合していますので、親ルート規則も子路参加が必要です。たとえば:

//     
const routers = new Router({
  base : "/test",
  //           、404、401 
  routes : [{
    path : "/",
    ...
    children : [{
      path : "login",
      ...
    },{
      path : "about",
      ...
    },{
      path : "order",
      ...
      children : [{
        path : "id"
      }]
    }]
  }]
})

//     
["/order/id"]; //         "/"     "/order/id" 、"/"     "/order"       "/order/id" == "/order/id"         path : "/",     path : "order"    。
2.5、動的登録

// ...        

const openRouters = [];
const authRouters = [{
  path : "order/list",
  // ...
  meta : {
    //       (      false  true       )
    isAuth : true
  }
}];

/*        */
async function AddRoutes() {
  //         
  let res = await POST(API.AUTH_RESOURCE_LISTSIDEMENU);
  try {
    const { code, data } = res || {};
    if (code === '000') {
      let newAuthRoutes = createAuthRouters(getAuthRouters(data))(authRouters, routes.options.base);
      //     
      routes.addRoutes([].concat(newAuthRoutes, openRouters));
      //      
      Store.commit('UPDATE_IS_ADD_ROUTERS', true);
      //       
      Store.commit('UPDATE_MENU_INFO', data);
    }
  } catch (error) {
    console.error('>>> AddRoutes() - error:', error);
  }
}

routes.beforeEach((to, from, next) => {
  const { meta, matched, path } = to;
  let isMatched = matched && matched.length > 0; //       
  let isLogin = Cookie.get("token") || null;
  let { isAuth } = (meta || {});
  if(isMatched){
    //      
    if(isAuth){
      //       
      if(isLogin){
        //      
        next(); //       
      }else{
        //      
        next("/login"); //     
      }
    }else{
      //        
      next(); //       
    }
  }else{
    //       
    if(isLogin){
      //      
      AddRoutes();
      next();
    }else{
      //      
      next("/login"); //     
    }
  }
})
2.6、分類整理

/*      */
let { origin } = window.location || {};
routes.beforeEach((to, from, next) => {
  const { meta, matched, path } = to;
  let isMatched = matched && matched.length > 0; //     
  let isAuth = (meta || {}).isAuth; //       
  let { isAddRoutes } = Store.state; //     
  let isLogin = Cookie.get('token') || null; //     
  if ((isMatched && !isAuth) || (isMatched && isAuth && isLogin)) {
    // next()
    // 1.     &&      
    // 2.     &&      &&   
    next();
  } else if ((isMatched && isAuth && !isLogin) || (!isMatched && !isLogin)) {
    //   
    // 1.     &&      &&    
    // 2.      &&    
    next(`/login?r=${origin}/e-lottery${path}`);
  } else if (!isMatched && isLogin && isAddRoutes) {
    // 404
    // 1.      &&    &&       
    next('/404');
  } else if (!isMatched && isLogin && !isAddRoutes) {
    //     
    // 1.      &&    &&        
    AddRoutes();
    next();
  }
});
うんこれはだいぶ楽になりました。
3、完全実現コード

// src/utils/index.js
const { pathToRegexp } = require('path-to-regexp');

export function getAuthRouters(authMenu) {
  let authRouters = [];
  (authMenu || []).forEach((item) => {
    const { resourceUrl, childMenu } = item;
    resourceUrl && authRouters.push(resourceUrl);
    if (childMenu && childMenu.length > 0) {
      //       
      authRouters = [...authRouters, ...getAuthRouters(childMenu)];
    }
  });
  return authRouters;
}
/**
 *
 * @param { Array } authRouters
 */
export function createAuthRouters(authRouters) {
  const isAuthUrl = (url) => {
    return (authRouters || []).some((cUrl) => {
      return pathToRegexp(url).toString() === pathToRegexp(cUrl).toString();
    });
  };
  return function createRouters(routers, upperPath) {
    let nRouters = [];
    (routers || []).forEach((item) => {
      const { children, path, name } = item;
      let isMatched = false,
        nItem = { ...item },
        fullPath = `${upperPath || ''}/${path}`.replace(/\/{2,}/, '/'),
        nChildren = null;
      children && (nChildren = createRouters(children, fullPath));
      // 1.      
      if (isAuthUrl(fullPath)) {
        isMatched = true;
      }
      // 2.       
      if (nChildren && nChildren.length > 0) {
        nItem.children = nChildren;
        isMatched = true;
      }
      //     
      if(name === "home"){
        isMatched = true;
      }
      // nItem
      isMatched && nRouters.push(nItem);
    });
    return nRouters;
  };
}

 
// src/router.js

import Vue from 'vue';
import Store from '@/store';
import Router from 'vue-router';
import Cookie from 'js-cookie';

const openRouters = [];
const authRouters = [{
  path : "order/list",
  // ...
  meta : {
    //       (      false  true       )
    isAuth : true
  }
}];

/*        */
async function AddRoutes() {
  //         
  let res = await POST(API.AUTH_RESOURCE_LISTSIDEMENU);
  try {
    const { code, data } = res || {};
    if (code === '000') {
      let newAuthRoutes = createAuthRouters(getAuthRouters(data))(authRouters, routes.options.base);
      //     
      routes.addRoutes([].concat(newAuthRoutes, openRouters));
      //      
      Store.commit('UPDATE_IS_ADD_ROUTERS', true);
      //       
      Store.commit('UPDATE_MENU_INFO', data);
    }
  } catch (error) {
    console.error('>>> AddRoutes() - error:', error);
  }
}


/*      */
let { origin } = window.location || {};
routes.beforeEach((to, from, next) => {
  const { meta, matched, path } = to;
  let isMatched = matched && matched.length > 0; //     
  let isAuth = (meta || {}).isAuth; //       
  let { isAddRoutes } = Store.state; //     
  let isLogin = Cookie.get('token') || null; //     
  if ((isMatched && !isAuth) || (isMatched && isAuth && isLogin)) {
    // next()
    // 1.     &&      
    // 2.     &&      &&   
    next();
  } else if ((isMatched && isAuth && !isLogin) || (!isMatched && !isLogin)) {
    //   
    // 1.     &&      &&    
    // 2.      &&    
    next(`/login?r=${origin}/e-lottery${path}`);
  } else if (!isMatched && isLogin && isAddRoutes) {
    // 404
    // 1.      &&    &&       
    next('/404');
  } else if (!isMatched && isLogin && !isAddRoutes) {
    //     
    // 1.      &&    &&        
    AddRoutes();
    next();
  }
});

フロントエンドはvue-routerを通じてルート権限の制御を実現することができますが、実際には疑似権限の制御であり、完全な制御を達成することができません。ルーティング権限を制御する必要があるシステムに対してバックエンド制御を採用することを強く示唆する。
ここで、vue-routerのルーティング権限の実現に関する記事を紹介します。これに関連して、Vue-routerのルーティング権限の内容については、以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。