美文网首页Vue
Vue 权限的三种实现方式(带源代码)

Vue 权限的三种实现方式(带源代码)

作者: HHHHy2019 | 来源:发表于2021-08-11 20:37 被阅读0次

    源代码:https://github.com/HYzihong/vue2-router-permissions

    几种方案

    对于后端返回来可选则的权限方案:

    • plan1(branch:plan1): 返回路由 name 的是否可访问的表,例如:{page1:true,page2:true,page3:false}
    • plan2(branch:plan2): 返回权限级别,比如:['admin','admin-delete','page1-all'],我们可以在路由表的 meta 中匹配角色
    • plan3(branch:plan3): 返回完整的路由表,例如:{[{path: "/",name: "Home",component: 'Home',},},不能返回绝对路径,要返回 Home

    下面的代码中都有完整的功能注释

    方案一:后端返回此用户可以访问的路由的name的表

    代码如下
    src/router/index

    
    ...
    import basicsRoutes from "./module/basicsRoutes";
    import { setTitle } from "../utils/router";
    import store from "../store";
    
    Vue.use(VueRouter);
    
    const router = new VueRouter({
      mode: "history",
      base: process.env.BASE_URL,
      basicsRoutes,
    });
    
    router.beforeEach((to, from, next) => {
      to.meta && setTitle(to.meta.title);
    
      let token = "...";
      if (token) {
        if (!store.state.router.hasGetRules) {
          // store
          //   .dispatch("authorization")
          //   .then((rules) => {
          
          // 这里为后端返回的路由name的权限表
          const rules = { Form: true, List: false, About: true };
          // 在store 中处理生成完整的路由表
          store
            .dispatch("concatRoutes", rules)
            .then((routers) => {
            // 合并路由表
              router.addRoutes(routers);
              next({ ...to, replace: true });
            })
            .catch(() => {
              next({ name: "login" });
            });
          // })
          // .catch(() => {
          //   token = '';
          //   next({ name: "login" });
          // });
        } else {
          next();
        }
      } else {
        if (to.name === "login") next();
        else next({ name: "login" });
      }
    });
    
    export default router;
    
    
    

    src/store/module/router

    
    // 带权限的路由
    import asyncRoutes from "../../router/module/asyncRoutes";
    // 基础的路由
    import basicsRoutes from "../../router/module/basicsRoutes";
    
    const state = {
      routers: basicsRoutes,// 这里是[]也没事
      hasGetRules: false,
    };
    
    const mutations = {
      CONCAT_ROUTES(state, routerList) {
        // 这里要注意路由表的前后问题
        state.routers = routerList.concat(basicsRoutes);
        state.hasGetRules = true;
      },
    };
    
    const getAccesRouterList = (basicsRoutes, rules) => {
      return basicsRoutes.filter((item) => {
        if (rules[item.name]) {
        // 如果有子路由,就进行递归操作
          if (item.children)
            item.children = getAccesRouterList(item.children, rules);
          return true;
        } else return false;
      });
    };
    
    const actions = {
      concatRoutes({ commit }, rules) {
        console.log(rules);
        return new Promise((resolve, reject) => {
          try {
            let routerList = [];
            // console.log(Object.entries(rules));
            /*
            ["Form", true]
            ["List", false]
            ["About", false]
            */
            // 如果所有页面都可以进行访问,则直接进行返回所有路由
            if (Object.entries(rules).every((item) => item[1])) {
              routerList = asyncRoutes;
            } else {
              // 递归asyncRoutes,看哪些页面有权限访问
              routerList = getAccesRouterList(asyncRoutes, rules);
            }
            commit("CONCAT_ROUTES", routerList);
            resolve(state.routers);
          } catch (err) {
            reject(err);
          }
        });
      },
    };
    
    export default {
      state,
      mutations,
      actions,
    };
    
    

    方案二:后端返回此用户的权限级别

    代码如下
    src/router/index

    ... // 省略其他代码,详细代码见github:https://github.com/HYzihong/vue2-router-permissions
    router.beforeEach((to, from, next) => {
      to.meta && setTitle(to.meta.title);
    
      let token = "...";
      if (token) {
        if (!store.state.router.hasGetRules) {
          // store
          //   .dispatch("authorization")
          //   .then((rules) => {
          const rules = ["about"]; // 这里传入是用户的权限级别
          store
            .dispatch("concatRoutes", rules)
            .then((routers) => {
              console.log(JSON.stringify(routers));
              router.addRoutes(routers);
              next({ ...to, replace: true });
            })
            .catch(() => {
              next({ name: "login" });
            });
          // })
          // .catch(() => {
          //   token = '';
          //   next({ name: "login" });
          // });
        } else {
          next();
        }
      } else {
        if (to.name === "login") next();
        else next({ name: "login" });
      }
    });
    
    
    

    src/store/module/router

    
    ... // 省略其他代码,详细代码见github:https://github.com/HYzihong/vue2-router-permissions
    
    const isRoleTrue = (role, rules) => {
        // 判断这个路由中的meta中的role的中是否包含此权限,
      return role.filter((_role) => rules.indexOf(_role) > -1).length > 0;
    };
    
    const getAccesRouterList = (basicsRoutes, rules) => {
      return basicsRoutes.filter((item) => {
        if (isRoleTrue(item.meta.role, rules)) {
        // 如果有子路由,就进行递归操作
          if (item.children)
            item.children = getAccesRouterList(item.children, rules);
          return true;
        } else return false;
      });
    };
    
    const actions = {
      concatRoutes({ commit }, rules) {
        return new Promise((resolve, reject) => {
          try {
            let routerList = [];
            // 如果是admin权限,则直接进行返回所有路由
            if (rules.indexOf("admin") > -1) {
              routerList = asyncRoutes;
            } else {
              // 递归asyncRoutes,看是否有权限访问
              routerList = getAccesRouterList(asyncRoutes, rules);
            }
            commit("CONCAT_ROUTES", routerList);
            resolve(state.routers);
          } catch (err) {
            reject(err);
          }
        });
      },
    };
    
    
    

    方案三:后端返回此用户的可以访问的所有的路由表

    代码如下
    src/router/index

    
    
    
    router.beforeEach((to, from, next) => {
      to.meta && setTitle(to.meta.title);
    
      let token = "...";
      if (token) {
        if (!store.state.router.hasGetRules) {
          // store
          //   .dispatch("authorization")
          //   .then((rules) => {
          store
            .dispatch("concatRoutes")
            .then((routers) => {
              console.log(routers);
              router.addRoutes(routers);
              next({ ...to, replace: true });
            })
            .catch(() => {
              next({ name: "login" });
            });
          // })
          // .catch(() => {
          //   token = '';
          //   next({ name: "login" });
          // });
        } else {
          next();
        }
      } else {
        if (to.name === "login") next();
        else next({ name: "login" });
      }
    });
    
    
    

    src/store/module/router

    
    
    import ajaxRouter from "../../utils/ajaxRouter";
    import routerMap from "../../utils/routerMap";
    
    // 方案一:简单的view结构使用
    const returnView = (url) => {
      return () => import(`../../views/${url}.vue`);
    };
    const initRoute = (router) => {
      router.component = returnView(router.component);
      if (router.children) getAccesRouterList(router.children);
      return router;
    };
    
    // 方案二:复杂的view结构使用
    const initRoute = (router) => {
      router.component = routerMap[router.component];
      if (router.children) getAccesRouterList(router.children);
      return router;
    };
    
    const getAccesRouterList = (ajaxRouter) => {
      return ajaxRouter.map((item) => initRoute(item));
    };
    
    const actions = {
      concatRoutes({ commit }) {
        return new Promise((resolve, reject) => {
          try {
            let routerList = [];
            routerList = getAccesRouterList(ajaxRouter);
            commit("CONCAT_ROUTES", routerList);
            console.log(routerList);
            resolve(state.routers);
          } catch (err) {
            reject(err);
          }
        });
      },
    };
    
    

    src/utils/ajaxRouter

    
    // 模拟后端返回的路由表
    const ajaxRouter = [
      {
        path: "/form",
        name: "Form",
        component: "Form",
      },
      {
        path: "/about",
        name: "About",
        component: "About",
        children: [
          {
            path: "aboutChild",
            name: "AboutChild",
            component: "AboutChild",
          },
        ],
      },
      {
        path: "/list",
        name: "List",
        component: "List",
      },
    ];
    export default ajaxRouter;
    
    
    

    src/utils/routerMap.js

    
    // 对应的view文件
    import Form from "../views/Form.vue";
    import About from "../views/About.vue";
    import AboutChild from "../views/AboutChild.vue";
    import List from "../views/List.vue";
    const routerMap = {
      Form: Form,
      About: About,
      List: List,
      AboutChild: AboutChild,
    };
    export default routerMap;
    
    

    相关文章

      网友评论

        本文标题:Vue 权限的三种实现方式(带源代码)

        本文链接:https://www.haomeiwen.com/subject/nexhbltx.html