vue以前端鑑權

  vue項目前端鑑權方式經常使用的有如下三種:前端

    一、渲染菜單時控制模塊按鈕的顯示隱藏(不足:直接輸入連接仍然能夠訪問模塊vue

    二、在路由導航守衛中攔截,針對沒有權限的模塊進行重定向(不足:每次訪問模塊都須要鑑定權限,模塊數量過多時會影響系統性能node

    三、藉助vue-router 2.x版本新加的API addRouters動態添加路由信息(不足:首次加載須要解析和添加,多跳轉一次路由vue-router

  綜上所述,權衡以後選擇了addRoutes動態添加,首屏加載時間可能會多出0.5s左右,加載一次以後後續就不須要再進行處理,能夠提高系統的可靠性與穩定性。具體使用以下:vuex

    一、定義固定路由,用於路由初始化,如:登陸頁、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
            }
        }
    }
});    

    二、路由導航守衛前置攔截async

      爲了方便,將路由權限信息保存到vuex中,在路由跳轉時,判斷state中是否存在menu信息,若是不存在,則向後端請求權限信息,此部分須要阻塞頁面的跳轉,改成同步執行;性能

      針對通常菜單嵌套路由,須要對路由信息最好進行扁平化處理,不然可能致使路由重複添加或者添加失敗(上級有父組件會致使重複添加,上級沒有組件單純嵌套會致使添加失敗)spa

//刷新頁面後,會致使動態生成的路由失效,須要從新走下添加路由操做
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()
    }
});

  注意code

    一、因爲路由時動態添加的,存儲在內存中,頁面刷新以後內存中變量也會消失,動態添加的路由也會隨之消失,因此每次刷新頁面須要從新走一遍添加路由的流程

    二、因爲路由是動態添加的,在路由跳轉時,添加的路由並無生效,因此還須要多跳轉一次頁面

  除此以外,按鈕的鑑權能夠經過自定義指令,動態傳入條件參數來實現按鈕的顯示隱藏,指令封裝以下:

/**
 * 節點鑑權
 * {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 >
相關文章
相關標籤/搜索