vue3中的动态路由设置和路由守卫

一、路由全局前置守卫设置。
permission.ts:

1、先判断是否有token。
没有token: 可以访问白名单页面;但未登录如果要去的不是白名单页面,让他到登录页面,然后再重定向到要去的页面。
有token(即登录成功):如果要去登录页,直接跳转;如果要去其他页面,

2、要先判断是否有用户信息—有用户信息:如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401;没有用户信息:先通过store获取用户信息,根据用户角色来获取并添加动态路由


import { RouteRecordRaw } from "vue-router"; //这行代码是使用 vue-router 库在 Vue.js 应用程序中定义路由所必需的。 RouteRecordRaw 接口用于定义 Vue.js 应用程序中的路由。

import { defineStore } from "pinia";
import {constantRoutes} from '@/router'; //拿到路由文件里的静态路由
import {listRoutes} from '@/api/system/menu'; //拿到路由api
import router from '@/router';
import NProgress from 'nprogress';
import useStore from '@/store';
import { RouteRecord } from 'vue-router';

NProgress.configure({ showSpinner: false }); //进度环显示/隐藏

// import.meta.glob 函数从文件系统导入多个模块
const modules = import.meta.glob('../../views/**/**.vue');


//白名单
const whiteList = ['/login', '/auth-redirect' ];

//路由全局前置守卫
router.beforeEach(async (to, from, next) => {
     NProgress.start();//进度条开始
     const { user, permission, app } = useStore();
     const hasToken = user.token;
     // 1.路由跳转前先判断是否有token
     if (hasToken) {
        // 1.1登录成功,跳转到首页
        if (to.path === '/login') {
            next({path: '/'});
            NProgress.done();
        } else {
            // 1.2登录成功,去其他页面----要判断是否有用户信息
            const hasGetUserInfo = user.roles.length > 0;

            //有用户信息
            if (hasGetUserInfo) {
                // 1.2.1如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401
                if (to.matched.length === 0) {
                    // next({name: ''})----通过名称导航到特定路由。name: 是我要导航到的路由名称
                    from.name ? next({name: from.name as any }) : next('/401');
                } else {
                    next();
                }
                
            } else { // 1.2.2 登录成功但 没有用户信息----先通过store获取用户信息,根据用户来获取并添加动态路由
                try {
                    await user.getUserInfo();
                    const roles = user.roles;

                    //通过获取到的角色拿到相应角色的动态路由信息
                    const accessedRoutes: any = await permission.generateRoutes(roles);
                    accessedRoutes.forEach((route:any) => {
                        //将动态路由里的每个路由添加进去
                        router.addRoute(route);

                    });
                    // 将当前路由信息与replace:true合并为一个新的对象,这个新的对象会被传入到next函数中。
                    // 表示要跳转到一个新的路由,并且使用replace模式进行跳转---会替换当前的路由记录,而不是添加一条新的记录。
                    next({...to, replace:true});
                    
                } catch (error) {//登录成功但获取用户信息失败----要移除token并跳转到登录页
                    await user.resetToken();
                    ElMessage.error((error as any) || 'Has Error');
                    next(`/login?redirect=${to.path}`);
                    NProgress.done();                 
                }              
            }           
        }
     } else { //2.没有token的话可以访问白名单页面(登录页面)
        // indexOf: 返回数组中第一次出现给定元素的下标,如果不存在就返回-1
        if (whiteList.indexOf(to.path) !== -1) {
            next();
        } else {
            // 未登录但要去的不是白名单页面-----让他到登录页面,然后再重定向到要去的页面
            next(`/login?redirect=${to.path}`);
            NProgress.done();
            
        }
        
     }

})

二、根据用户角色来筛选获取并添加动态路由
store下的permission.ts:

const usePermissionStore = defineStore({
    id:'permission',
    state: ():PermissionState => ({
        routes: [], //总共的路由
        addRoutes: [], //动态添加的路由
    }),
    actions: {
        setRoutes(routes: RouteRecordRaw[]) {
            this.addRoutes = routes;
            this.routes = constantRoutes.concat(routes);
        },
        // 根据角色筛选得到的动态路由   重要一步!
        generateRoutes(roles: string[]){
            return new Promise((resolve, reject) => {
                //从接口获取路由列表
                listRoutes().then((response) => {
                    const asyncRoutes = response.data;//从接口获取的所有路由
                    const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);//根据角色筛选得到的动态路由   重要一步!
                    this.setRoutes(accessedRoutes); //把获得的动态路由给store赋值

                    resolve(accessedRoutes);
                }).catch((error) => {
                    reject(error)
                })

            })

        }

        
    }
})
export default usePermissionStore;




//根据角色过滤所有路由生成动态路由
export const filterAsyncRoutes = (routes:RouteRecordRaw[], roles: string[]) => {
    // 对每一个路由进行遍历
    routes.forEach((route) => {
        //定义一个空数组----放过滤出来的动态路由
        const res: RouteRecordRaw[] = [];
        //拿到每一个路由项并对里面的属性进行解构
        const tmp = {...route} as any;

        //如果这个角色有这个路由权限就说明可以访问路由
        if (hasPermission(roles, tmp)) {//此角色可以访问路由后就要配置路由信息了
            if (tmp.component == 'Layout') {
                tmp.component = Layout;
            } else {
                //如果不是Layout组件,拿到其他组件名称
                const component = modules[`../../views/${tmp.component}.vue`] as any;
                if (component) {
                    tmp.component = modules[`../../views/${tmp.component}.vue`];
                    
                } else {
                    //如果这个组件不存在 就跳到404页面
                    tmp.component = modules[`../../views/error-page/404.vue`]
                    
                } 
                
            }
            res.push(tmp);

            if(tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles);
            }
        }
    });
    return res;

}





//对某个角色是否对某个路由拥有权限进行判断------ 根据不同角色判断路由是否存在
const hasPermission = (roles: string[], route: RouteRecord) => {
    if(route.meta && route.meta.roles) {
        //如果是管理员--肯定有权限
        if(roles.includes('ROOT')) {
            return true;
        }
        //如果不是管理员
        return roles.some((role) => {
            if(route.meta?.roles !== undefined) {
                //实例路由里面的roles里包含实际登录的用户role--返回true,说明这个用户有路由权限
                return (route.meta.roles as stirng[]).includes(role);
            }

        })


    }
    return false;


}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue2,我们可以使用全局的路由守卫来控制路由的跳转和访问权限。Vue3路由守卫也有所改变。 首先,Vue2的全局路由守卫包括了beforeEach、beforeResolve和afterEach等钩子函数,这些钩子函数分别在路由跳转之前、解析完组件之前以及路由跳转完成之后触发。而在Vue3路由守卫的写法更加灵活和精简,使用了新的Composition API的onBeforeRouteLeave、onBeforeRouteUpdate和onBeforeRouteEnter等函数来替代全局路由守卫。 其次,Vue2路由守卫是通过传入next函数来进行路由的跳转控制,可以通过调用next函数传入一个新的路由路径来进行跳转,也可以通过调用next(false)来阻止路由的跳转。而在Vue3路由守卫使用了Promise的方式来控制路由的跳转。可以通过返回一个Promise对象来决定路由是否跳转或者延迟路由的跳转。 此外,Vue2路由守卫是基于全局的,即对所有路由都生效。而在Vue3路由守卫可以局部应用于具体的路由或者路由组件,在组合式API可以通过在组件内部使用setup函数来定义特定路由的守卫。 综上所述,Vue3路由守卫相比Vue2有了一些改变,使用了新的Composition API和Promise的方式来实现。同时,Vue3路由守卫更加灵活和精简,可以更方便地控制路由的跳转和访问权限。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [vue2和vue3的区别(由浅入深)](https://blog.csdn.net/weixin_42974827/article/details/126560362)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值