Vue implements dynamic routing

In many cases, the routing of our project is configured in the front end,
but sometimes in order to carry out comprehensive permission control, we will need to give the routing table in the background, and then render the front end. No need to configure in the front end.

The following mainly talks about ideas

1. Communicate the data with the little brother in the background 把我们前端配置的路由表数据给他, he can understand

2、拿到数据需要我们自己再处理

The componentbackend in the routing can not be given, here we only need the backend little brother to componentgive the data according to the front-end path we provide , we can load it in a loop

//view就是后台给的数据
return () => import(`@/view/modules/${view}`);

This way we get the most important data, component.

3. Process the data provided by the background into the routing table we need
4. Add to the routing

 Router.addRoutes(路由数据)

The following talk about my implementation process in the project

1. Create a new router.js

Do some basic routing operations, such as importing packages, because we still have to manually put them into the route after we get the data. We
will also write menu data that does not need to be provided in the background, such as our test page or login

import Vue from "vue";
import Router from "vue-router";
import AppMain from "@/view/modules/main/index";
Vue.use(Router);
export const _CONSTANTS_ROUTERS =
[
    {
        path: "/login",
        component: () => import("@/view/modules/login/index"),
        hidden: true
    },
    {
        path: "",
        component: AppMain,
        redirect: "/dashboard",
        children: [
            {
                path: "/dashboard",
                component: () => import("@/view/modules/dashboard/index"),
                name: "Dashboard",
                meta: { title: "首页", icon: "dashboard", noCache: true }
            }
        ]
    }
];
export default new Router({
    mode: "history",
    // 解决vue框架页面跳转有白色不可追踪色块的bug
    scrollBehavior: () => ({ x: 0, y: 0 }),
    // scrollBehavior: () => ({ y: 0 }),
    routes: _CONSTANTS_ROUTERS
});

The basic routing table has been established

2. When do we get the complete routing table data

At this time, we must think of routing hook function, of course, do it in Router.beforeEach

Router.beforeEach((to, from, next) =>
{
    NProgress.start();
    if (!Token.isEmpty())
    { 
        if (to.path === "/login")
        {
            next({ path: "/" });
            NProgress.done(); 
        }
        else if (to.path === "/404")
        {
            next();
            NProgress.done();
        }
        else
        {
            // 判断当前用户是否已拉取完角色信息
            if (Store.getters.roles.length === 0)
            {
                 //拉取路由数据
ACLRepo.listMenuTreeOfCurrentUser().then(response =>
                    {
                        Store.dispatch("generateRoutes", response).then(() =>
                        {
                            // 根据roles权限生成可访问的路由表
                            Router.addRoutes(Store.getters.addRouters); // 动态添加可访问路由表
                            next({ ...to, replace: true }); // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                        });
                    });
            }
            else
            {
                 next();
            }
        }
    }
    else
    {
       next();
    }
});

3. Repackaging routing data

generateRoutes

import { _CONSTANTS_ROUTERS } from "@/scripts/router";
import AppMain from "@/view/modules/main/index";
const _PERMISSION = {
    state: {
        routers: _CONSTANTS_ROUTERS,
        addRouters: []
    },
    mutations: {
        setRouters: (state, routers) =>
        {
            state.addRouters = routers;
            //和已经存在的路由表拼接
            state.routers = _CONSTANTS_ROUTERS.concat(routers);
        }
    },
    actions: {
        generateRoutes({ commit }, response)
        {
            let asyncRouters = filterAsyncRouter(response);
            asyncRouters.push({ path: "*", redirect: "/404", hidden: true });
            commit("setRouters", asyncRouters);
        }
    }
};

function filterAsyncRouter(routers)
{
    // 遍历后台传来的路由字符串,转换为组件对象
    let accessedRouters = routers.filter(router =>
    {
        if (router.meta)
        {
            // 默认图标处理
            router.meta.icon = router.meta.icon ? router.meta.icon : "component";
        }
        if (router.component === "main")
        {
            // Main组件特殊处理
            router.component = AppMain;
        }
        else
        {
            //处理组件---重点
            router.component = loadView(router.component);
        }
        //存在子集
        if (router.children && router.children.length)
        {
            router.children = filterAsyncRouter(router.children);
        }
        return true;
    });
    return accessedRouters;
}
function loadView(view)
{
    // 路由懒加载
    return () => import(`@/view/modules/${view}`);
}
export default _PERMISSION;

This is actually done here, clear the line of thought

Published 252 original articles · Like 106 · Visits 30,000+

Guess you like

Origin blog.csdn.net/weixin_42554191/article/details/105459706