zoukankan      html  css  js  c++  java
  • vue之前端鉴权

      vue项目前端鉴权方式常用的有以下三种:

        1、渲染菜单时控制模块按钮的显示隐藏(不足:直接输入链接仍然可以访问模块

        2、在路由导航守卫中拦截,针对没有权限的模块进行重定向(不足:每次访问模块都需要鉴定权限,模块数量过多时会影响系统性能

        3、借助vue-router 2.x版本新加的API addRouters动态添加路由信息(不足:首次加载需要解析和添加,多跳转一次路由

      综上所述,权衡之后选择了addRoutes动态添加,首屏加载时间可能会多出0.5s左右,加载一次之后后续就不需要再进行处理,可以提升系统的可靠性与稳定性。具体使用如下:

        1、定义固定路由,用于路由初始化,如:登录页、404页面等

    const router = new Router({
        // mode: 'history',
        // base: base,
        routes: [
            {
                path: '/',
                name: '',
                component: () => import('@/views/login/login') ,
                meta:{label: '登录'}
            }
        ],
        scrollBehavior(to, from, savedPosition) {
            if (savedPosition) {
                return savedPosition
            } else {
                return {
                    x: 0,
                    y: 0
                }
            }
        }
    });    

        2、路由导航守卫前置拦截

          为了方便,将路由权限信息保存到vuex中,在路由跳转时,判断state中是否存在menu信息,如果不存在,则向后端请求权限信息,此部分需要阻塞页面的跳转,改为同步执行;

          针对一般菜单嵌套路由,需要对路由信息最好进行扁平化处理,否则可能导致路由重复添加或者添加失败(上级有父组件会导致重复添加,上级没有组件单纯嵌套会导致添加失败)

    //刷新页面后,会导致动态生成的路由失效,需要重新走下添加路由操作
    let registerRouteRefresh = true;
    
    router.beforeEach(async (to, from, next) => {
        //如果不存在菜单信息,则走动态授权
        if (store.state.menus.length === 0) {
            //确保初始化信息完成后才会执行下一步动作
            await init();
            let nodesList = [];
            //递归获取权限菜单列表
            initNodes(menuNodes, nodesList);
            store.commit('UPDATE_DATA', {
                key: 'menus',
                value: nodesList
            });
            //获取路由权限信息
            const asyncNodes = getAsyncNodes(nodesList, []);
            //添加拥有权限的路由信息
            router.addRoutes(asyncNodes);
            registerRouteRefresh = false;
            next({
                ...to,
                replace: true
            })
        }else {
            //如果是页面刷新,需要重新加载下动态路由
            if (registerRouteRefresh) {
                let nodesList = [];
                //递归获取权限菜单列表
                initNodes(menuNodes, nodesList);
                //获取路由权限信息
                const asyncNodes = getAsyncNodes(nodesList, []);
                //添加拥有权限的路由信息
                router.addRoutes(asyncNodes);
                registerRouteRefresh = false;
                //确保路由加载完成
                next({
                    ...to,
                    replace: true
                })
            }
            next()
        }
    });

      注意

        1、由于路由时动态添加的,存储在内存中,页面刷新之后内存中变量也会消失,动态添加的路由也会随之消失,所以每次刷新页面需要重新走一遍添加路由的流程

        2、由于路由是动态添加的,在路由跳转时,添加的路由并没有生效,所以还需要多跳转一次页面

      除此之外,按钮的鉴权可以通过自定义指令,动态传入条件参数来实现按钮的显示隐藏,指令封装如下:

    /**
     * 节点鉴权
     * {code: menuCode, flag:条件生效取反}
     */
    Vue.directive('permission', {
        bind(el, binding) {
            let vv = binding.value;
            if (vv.flag) {
                el.style.display = hasPermission(vv.code) ? 'none' : 'block';
            } else {
                el.style.display = hasPermission(vv.code) ? 'block' : 'none';
            }
        }
    });

      使用方法:

    <button v-permission="{code: 123}"></button >

          

  • 相关阅读:
    js原型杂谈
    arguments.callee.caller
    $resource
    sql的四种匹配模式
    AMD规范
    module.ngdoc
    angularjs杂谈
    浏览器前缀
    css21规范学习
    <meta>标签
  • 原文地址:https://www.cnblogs.com/gerry2019/p/11045555.html
Copyright © 2011-2022 走看看