vue权限控制-- 路由鉴权,菜单动态渲染,自定义指令渲染按钮,递归处理数据

敖涵容
2023-12-01

vue权限控制-- 路由鉴权,菜单动态渲染,自定义指令渲染按钮,递归处理数据

main.js中的路由守卫

router.beforeEach((to, from ,next)=>{
    if(!store.state.token) {
        if(to.matched.length > 0 && to.matched[to.matched.length - 1].meta.requireAuth) {
            // console.log("不需要登录")
            next()
        }else{
            // console.log("需要登录");
            if(to.path == '/login') {
                next();
            }else{
                next("/login")
            }
        }
    }else{
        if(!store.state.permissionList) {   // 登录过了,没有权限列表, 请求获取权限列表
            store.dispatch("SET_PERMISSION").then(()=>{
                next({
                    path: to.fullPath
                })
            })
        }else{
            console.log("登录过, 已经有权限列表了")
            if(to.path != '/login') {
                next();
            }else{
                next(from.fullPath)
            }
        }
    }
})

路由表中根部暴露出来的路由(实际按自己的路由表写)

export const rootRoutes = [
    {
        path: '/',
        name:'Layout',
        component: ()=>import("@/views/layout"),
        link: '/',
        meta: {
            requireAuth: false,
            name: 'wrap'
        },
        children: [
            {
                path: 'scholl',
                name: 'Scholl',
                component: ()=>import("@/views/layout/views/scholl/index.vue"),
                link: '/scholl',
                meta: {
                    requireAuth: true,
                    name: '学校'
                },
                children: [
                    {
                        path: 'addScholl',
                        name: 'AddScholl',
                        link: '/scholl/addScholl',
                        component: ()=>import("@/views/layout/views/scholl/views/addScholl/index.vue"),
                        meta: {
                            requireAuth: false,
                            name: '新增学校'
                        },
                    },
                    {
                        path: 'deleteScholl',
                        name: 'DeleteScholl',
                        link: '/scholl/deleteScholl',
                        component: ()=>import("@/views/layout/views/scholl/views/deleteScholl/index.vue"),
                        meta: {
                            requireAuth: true,
                            name: '删除学校'
                        }
                    }
                ]
            },
            {
                path: 'class',
                name: 'Class',
                link: '/class',
                component: ()=>import("@/views/layout/views/class/index.vue"),
                meta: {
                    requireAuth: false,
                    name: '班级'
                },
                children: [
                    {
                        path: 'addClass',
                        name: 'AddClass',
                        link: '/class/addClass',
                        component: ()=>import("@/views/layout/views/class/addClass/index.vue"),
                        meta: {
                            requireAuth: false,
                            name: '新增班级'
                        }
                    },
                    {
                        path: 'deleteClass',
                        name: 'DeleteClass',
                        link: '/class/deleteClass',
                        component: ()=>import("@/views/layout/views/class/deleteClass/index.vue"),
                        meta: {
                            requireAuth: true,
                            name: '删除班级'
                        }
                    }
                ]
            }
        ]
    },
    // {
    //   path: '*',
    //   component: ()=>import("@/views/404")
    // }
];

store中的state

export default {
    // token
	get token() {
        return sessionStorage.getItem("token")
    },
    set token(value) {
        sessionStorage.setItem("token", value);
    },

    // 权限列表
    permissionList: null,
    // 菜单列表
    menuList: []
}

mutation

export default {
     // 设置token
    SET_TOKEN(state, token) {
        state.token = token;
    },
    // 清空token
    CLEAR_TOKEN(state) {
        state.token = "";
    },

    // 设置权限列表
    SET_PERMISSIONS(state, permissionList) {
        state.permissionList = permissionList;
    },
     
     // 清空权限列表
    CLEAR_PERMISSIONS(state) {
        state.permissionList = null;
    },

     // 设置菜单列表
    SET_MENUS(state, menuList) {
        state.menuList = menuList;
    },

    // 清空菜单列表
    CLEAR_MENUS(state, menuList) {
        state.menuList = [];
    }
}

action中

import { permission } from "@/api"
import router, {rootRoutes} from "@/router"
import { recursionRouters, setDefaultRouter } from "@/utils/handleRouter"
export default {
     async SET_PERMISSION({commit, state}, permissionList) {

        let data = await permission(state.token),
            realRouter = [];
        // 写好的路由和请求的路由做比对,得到当前登录人的真实路由权限
         realRouter = recursionRouters(data, rootRoutes);
         // 添加404页面
         realRouter.push({
             path: '*',
             component: ()=>import("@/views/404")
         });
         // 设置默认路由
         setDefaultRouter(realRouter);
         // 路由鉴权
         router.addRoute("App", realRouter[0]);
         router.addRoute("App", realRouter[1]);
         // 存储菜单列表
         commit("SET_MENUS", recursivefilter(realRouter[0].children));
         // 存储路由权限
         commit("SET_PERMISSIONS", realRouter)

         // 查看加进去的路由表
         console.log(router.getRoutes())
    }
}

function recursivefilter(arr) {
    return arr.filter(item => {
        if (item.meta.white) {
            return false
        }
        if(item.children && item.children.length > 0){
            item.children = recursivefilter(item.children)
        }
        return true
    })
}

utils中创建 handleRouterjs文件

// 路由表里面写的路由和后台查询的路由比对,得到当前登录人的真实路由
export function recursionRouters(userRouter=[], allRouter=[]) {
    let realRouter = [];
    allRouter.forEach(v => {
        userRouter.forEach((item, index)=>{
            if(item.name == v.meta.name) {
                if(item.children && item.children.length > 0) {
                    v.children = recursionRouters(item.children, v.children);
                }
                realRouter.push(v);
            }
        })
    });
    return realRouter;
}

// 设置默认路由
export function setDefaultRouter(routes) {
    routes.forEach((v, i)=>{
        if(v.children && v.children.length) {
            v.redirect = {name: v.children[0].name}
            setDefaultRouter(v.children);
        }
    })
}

菜单动态渲染

slider组件中

<el-menu :default-active="this.$route.path" class="el-menu-vertical" :collapse="isCollapse" router unique-opened>
     <template v-for="(item, index) in menuList">   <!-- menuList缓存在vuex中的菜单列表 -->
         <MenuItems :item="item" :key="index"></MenuItems>
     </template>
</el-menu>

MenuItems组件中

<el-submenu :index="item.name" v-if="item.children && item.children.length">
    <template slot="title">
        <i :class="item.meta.icon"></i>
        <span slot="title">{{item.meta.name}}</span>
    </template>
    <template v-for="(innerItem, innerIndex) in item.children" v-if="item.children && item.children.length">
        <MenuItems :item="innerItem" :key="innerIndex"></MenuItems>
    </template>
</el-submenu>
<template v-else>
    <el-menu-item :index="item.link || item.path">
        <template slot="title">
            <i :class="item.meta.icon"></i>
            <span>{{item.meta.name}}</span>
        </template>
    </el-menu-item>
</template>

自定义指令渲染按钮

// 菜单自定义指令控制显示或隐藏
Vue.prototype.$_hasMenu = function(val) {
    if(store.state.buttonList) {
        let list = JSON.parse(store.state.buttonList);
        for (let i = 0; i < list.length; i++) {
            if (list[i].selfIndex == val) {
                return true;
            }
        }
    }
    return false;
}
Vue.directive("hasMenu", {
    inserted: function (el, binding) {
        if(!Vue.prototype.$_hasMenu(binding.value)) {
            setTimeout(()=>{
                el.parentNode && el.parentNode.removeChild(el);
            }, 0)
        }
    }
})

递归处理数据

// 递归方法处理
export function recursion(array) {
    let parentList = [];
    for (let i = 0; i < array.length; i++) {
        if (!array[i].parentId) {
            parentList.push(array[i]);
        }
    }

    toDoRecursion(parentList);

    function toDoRecursion(arr) {
        for (let i = 0; i < arr.length; i++) {
            let middleArr = [];
            for (let j = 0; j < array.length; j++) {
                if (arr[i].id == array[j].parentId) {
                    middleArr.push(array[j]);
                }
            }
            if (middleArr.length != 0) {
                toDoRecursion(middleArr);
                arr[i].children = middleArr
            }
        }
    }
    return parentList;
}
 类似资料: