美文网首页前端
vue 实现动态路由

vue 实现动态路由

作者: super静_jingjing | 来源:发表于2019-03-20 19:29 被阅读0次

    很多时候我们在项目的路由都是在前端配置好的
    但是有的时候为了进行全面的权限控制,会需要后台给出路由表,前端再渲染。不用在前端配置。

    下面主要讲一下思路
    1、和后台小哥哥沟通好数据,把我们前端配置的路由表数据给他,他就能看懂了

    2、拿到数据需要我们自己再处理
    路由中的component后台是给不了的,这里我们只需要后台小哥哥按照我们提供的前端component路径给数据,我们循环加载就可以了

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

    这样我们就拿到了最重要的数据,即component。

    3、把后台提供的数据处理成我们需要的路由表
    4、添加到路由中

     Router.addRoutes(路由数据)
    

    以下讲一下我在项目中实现过程
    1、新建一个router.js
    里面做些基本的路由操作,比如导入包,因为我们拿到数据之后还是要自己手动去放到路由中去的
    也会写一写不需要后台提供的菜单数据,比如我们测试页面或者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
    });
    

    基本路由表已经建立好了

    2、我们在什么时候进行获取完整的路由表数据
    这个时候我们就要想到路由钩子函数,当然是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、路由数据重新封装
    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;
    

    到这里其实就完成了,理清楚思路,其实很简单

    相关文章

      网友评论

        本文标题:vue 实现动态路由

        本文链接:https://www.haomeiwen.com/subject/tfgtvqtx.html