Vue3动态路由与路由守卫

在正式的案例中,我们需要登录后从服务器获取token后再用token来获取数据,而且对于用户也有不同的角色(管理员和普通用户),因此实际项目的路由应该根据权限进行动态获取,下面就对之前实现的后台管理项目进行修改,将静态路由修改成动态路由。

首先增加本地mock数据仓库,封装api:

//本地mock模拟数据
const adminMenu = [
    {
        path: '/adminhome',
        name: 'adminhome',
        meta: {
            label: '管理员主页',
            icon: 'HomeFilled',
            isShow: true,
        },
        url: "home/AdminHome"
    },
    {
        path: '/manage1',
        name: 'manage1',
        meta: {
            label: '管理页面1',
            icon: 'Setting',
            isShow: true,
        },
        url: "Admin/Manage1"
    },
    {
        path: '/manage2',
        name: 'manage2',
        meta: {
            label: '管理页面2',
            icon: 'Setting',
            isShow: true,
        },
        url: "Admin/Manage2"
    },
];
const userMenu = [
    {
        path: '/userhome',
        name: 'userhome',
        meta: {
            label: '用户主页',
            icon: 'HomeFilled',
            isShow: true,
        },
        url: "home/UserHome"
    },
    {
        path: '/userPage1',
        name: 'userPage1',
        meta: {
            label: '页面1',
            icon: 'Setting',
            isShow: true,
        },
        url: "User/UserPage1"
    },
    {
        path: '/userPage2',
        name: 'userPage2',
        meta: {
            label: '页面2',
            icon: 'Setting',
            isShow: true,
        },
        url: "User/UserPage2"
    },
];

export default {
    getMenuDataByRole: (params) => {
        // console.log("==========Menu Mock=============");
        // console.log(params);
        let requestData = JSON.parse(params.body);      //传入数据是json
        let rsList = [];
        // console.log("requestData.role: " + requestData.role);
        if (requestData.role === "admin") {
            rsList = adminMenu;
        }
        else {
            rsList = userMenu;
        }
        return {
            code: 200,
            data: {
                routers: rsList
            }
        }
    },
}

然后在登录页面实现登录逻辑,并获取服务器返回的token和role并进行存储,本项目将之存储与vuex中,实际可以存储在cookie或者localstorage中实现登录状态保存等功能,然后就需要修改路由导航:

"use strict";
import { ref } from "vue";
import { createRouter, createWebHashHistory, } from 'vue-router'
import store from '../store/index'
import api from '../api/api';

let inited = false;   //是否加载过
const routes = [
    {
        path: '/',
        name: "login",
        component: () => import('../views/login/Login.vue')
    },
    {
        path: '/main',
        name: 'main',
        component: () => import(/* webpackChunkName: "[main]"*/'../views/Main.vue')
    },
]

const router = createRouter({
    history: createWebHashHistory(),//调用
    routes
})

// 路由拦截与动态路由
router.beforeEach(async (to) => {
    // console.log("==============Router===============");
    // 登录拦截
    const token = store.state.userToken;
    // console.log("token: " + token);
    if (!token && to.name !== "login") {
        return '/';
    }
    if (to.name !== 'login' && token) {
        if (!inited) {  //还未动态加载路由
            //动态路由
            const role = store.state.userRole;
            let routerData = ref([]);
            // const { proxy } = getCurrentInstance();
            let resObj = await api.getMenuData({ role: role });
            routerData = resObj.routers;
            // console.log(routerData);
            routerData.forEach((v) => {
                let viewUrl = `../views/${v.url}.vue`;
                // console.log(viewUrl);
                let routerObj = {
                    path: v.path,
                    name: v.name,
                    meta: v.meta,
                    component: () => import(/* @vite-ignore *//* webpackChunkName: "[request]"*/ viewUrl),
                }
                // console.log(routerObj);
                router.addRoute("main", routerObj);
            })
            // console.log(routerData);
            inited = true;
            // router.replace(to.name)
            console.log();
        }
    }
    else {
        inited = false;
    }

});

export default router;           //导出路由

上述的逻辑是,使用一个是否进行了路由列表初始化的标键变量inited来进行标键是否进行了路由表的初始化,然后先拦截非登录的访问页面请求,再根据role来向服务器请求对应的路由列表。

注意!!!在动态import时vite会给我们抛出警告,这里我确保url正确,所以采用/* @vite-ignore */注释忽略了,实际参考下面可以解决。

vue3+vite2警告提示The above dynamic import cannot be analyzed by vite问题,vite中import动态引入_云秒的博客-CSDN博客

 

你可能感兴趣的:(javascript,开发语言,ecmascript)