通过接收后台返回数据来实现Vue动态路由

应用场景

用户登录成功后,通过后台接口返回该用户可访问的路由

router配置

src/router/index.js文件

import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);

// 解决Vue-Router升级导致的Uncaught(in promise) navigation guard问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject)
    return originalPush.call(this, location, onResolve, onReject);
    return originalPush.call(this, location).catch((err) => err);
};

// 公共路由
const constantRoutes = [
    {
        path: '/login',
        name: 'login',
        component: () => import('@/views/login/index'),
        meta: {
            title: '登录',
        },
        hidden: true
    },
    {
        path: '/404',
        component: () => import('@/views/error/404'),
        meta: {
            title: '404',
        },
        hidden: true
    },
];

// 清空路由表
export const asyncRouterMap = [];

const createRouter = () =>
    new VueRouter({
        // mode: 'history', // require service support
        scrollBehavior: () => ({ y: 0 }),
        routes: constantRoutes,
    });

const router = createRouter();

// 重置路由,放置重复添加崩溃
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

权限配置

src/permission.js文件,在入口文件中引入

import router from './router';
import store from './store';
import { getToken } from '@/utils/auth';
import Layout from '@/views/main/index'
import menuData from '@/mock/menuData.json';

// 给后台接口数据整形
const arr = menuData.data;
let listL1 = [], listL2 = [];
for (let index = 0; index < arr.length; index++) {
    if(arr[index].level === 1) {
        listL1.push(arr[index])
    } else if(arr[index].level === 2){
        const str = arr[index].url;
        arr[index].path = str.slice(str.indexOf('/'),str.indexOf('.'));
        listL2.push(arr[index])
    }
}
for (let i = 0; i < listL1.length; i++) {
    listL1[i].children = listL2.filter(item=>item.parentId === listL1[i].id)
}


const whiteList = ['/login']; // 没有重定向白名单

router.beforeEach(async (to, from, next) => {
    // 设置页面标题
    if(to.name){
        document.title = to.name //修改网页的title
    }

    // 判断用户是否已经登录
    const hasToken = getToken();
    // debugger
    if (hasToken) {
        if (to.path === '/login') {
            // 如果已经登录,则重定向到主页
            next({ path: '/index' });
        } else {
            const hasGetUserRouter = store.state.dynamicRoutes; // 是否有路由表
            if (hasGetUserRouter.length > 0) {
                // const button = to.meta.button
                // store.commit('permission/SET_BUTTON', button) // 设置当前页面按钮权限
                next();
            } else {
                
                try {
                    
                    store.dispatch('dynamicRoutes', listL1)
                    routerGo(to, next, listL1);
                } catch (error) {
                    store.dispatch('token')
                    next(`/login`);
                }
            }
        }
    } else {
        if (whiteList.indexOf(to.path) !== -1) {
            next();
        } else {
            next(`/login`);
        }
    }
});

router.afterEach(() => {
    // finish progress bar 进度条
    //   NProgress.done()
});
// 根页面
const menuRoot = {
    path: '/',
    component: Layout,
    redirect: '/index',
    name: '主页面',
    meta: { title: '主页面', icon: 'el-icon-s-help' },
    children: [],
}

// 导航到一个新的路由方法封装
function routerGo(to, next, routerList) {
    const newRouter = filterAsyncRouter(routerList); // 过滤路由

    const menuRouterTemp = { ...menuRoot };
    menuRouterTemp.children =  newRouter
    router.options.routes.push(menuRouterTemp);
    router.addRoute(menuRouterTemp);
    router.addRoute({ path: '*', redirect: '/404', hidden: true });

    next({ ...to, replace: true });
}

// 过滤路由方法封装-拼接路径
function filterAsyncRouter(asyncRouterMap,res) {
    res = res || [];
    asyncRouterMap.forEach((elem) => {
        if (!elem.children) {
            let obj = { ...elem };
            obj.component = (resolve) =>
                require([`@/views${elem.path}`], resolve);
            res.push(obj);
        } else {
            filterAsyncRouter(elem.children, res);
        }
    });
    return res;
}

展示效果

demo地址在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42563079/article/details/128951402