vue结合vuex和vue-router实现导航栏动态路由

模拟后台接口数据

{
    "code":0,
    "msg":"",
    "count":19,
    "data":[
        {
            "authorityId": 1,
            "meta": {"title":"最近","type":1},//type是我为了区分侧边栏的上下展示需要的参数
            "name":"near",//路由名称
            "path": "/near/index",//路由路径
            "icon": "el-icon-message-solid",//图标
            "component": "near/index",//组件路径
            "authority": null,//携带的用户信息,方便日后的权限管理
            "children":null//子路由
        },
        {
            "authorityId": 2,
            "meta": {"title":"小计","type":1},
            "name":"subtotal",
            "path": "/subtotal/index",
            "icon": "el-icon-s-claim",
            "component": "subtotal/index",
            "authority": null,
            "children":null
        },
        {
            "authorityId": 3,
            "meta": {"title":"收藏","type":1},
            "name":"collection",
            "path": "/collection/index",
            "icon": "el-icon-time",
            "component": "collection/index",
            "authority": null,
            "children":null
        },
        {
            "authorityId": 4,
            "meta": {"title":"记事本","type":2},
            "name":"note",
            "path": "/note/index",
            "icon": "el-icon-notebook-2",
            "component": "note/index",
            "authority": null,
            "children":null
        },
        {
            "authorityId": 5,
            "meta": {"title":"团队","type":2},
            "name":"organization",
            "path": "/organization/index",
            "icon": "el-icon-s-custom",
            "component": "organization/index",
            "authority": null,
            "children":[
                {
                    "authorityId": 6,
                    "meta": {"title":"javaweb"},
                    "name":"organization1",
                    "path": "/organization1/index",
                    "icon": "el-icon-s-custom",
                    "component": "organization/index",
                    "authority": null,
                    "children":null
                },
                {
                    "authorityId": 7,
                    "meta": {"title":"软件测试"},
                    "name":"organization2",
                    "path": "/organization2/index",
                    "icon": "el-icon-s-custom",
                    "component": "organization/index",
                    "authority": null,
                    "children":null
                }
            ]
        },
        {
            "authorityId": 8,
            "meta": {"title":"日志","type":2},
            "name":"log",
            "path": "/log/index",
            "icon": "el-icon-date",
            "component": "log/index",
            "authority": null,
            "children":null
        }
    ]
}

创建router/index.js

不需要动态获取的路由信息可以直接存放在constantRouterMap变量中

export const constantRouterMap=[//没有涉及权限的静态路由
    {
        path:'/',
        name:'login',
        component:login,
        hidden:true
    },
    {
        path:'/404',
        name:'404',
        component:Nfind,
        hidden:true
    }
]

将静态路由赋给routes管理

const createRouter=()=>new VueRouter({
    mode:'history',//history模式不会在路由上加#符号
    routes:constantRouterMap
})

当获取到接口数据之后,为了能让接口数据中的路由信息可以正常的展示在页面,需要对路由信息进行处理,下面方法的作用是遍历接口数据拼接路由信息使其成为一个可以被router识别展示的路由,如果路由中还有子路由,就再次调用此方法,将子路由信息赋给父路由,这样就形成了一个二级菜单

export function getAsyncRoutes(routes){
    const res=[]
    const keys=['path', 'name', 'children', 'redirect', 'meta','icon']//定义路由需要的自定义名
    // console.log(routes,"routes")
    routes.forEach(item=>{
        const newItem={}
        if(item.component){
            newItem.path=item.path
            newItem.meta=item.meta
            newItem.component=resolve=>require([`@/views/${item.component}`],resolve)
            res.push(newItem)
        }
        for(const key in item){
            if(keys.includes(key)){
                newItem[key]=item[key]
            }
        }
        if(newItem.children!=null){
            newItem.children=getAsyncRoutes(item.children)
        }
    })
    return res;
}

由于侧边栏和右侧内容区是一个界面,当左侧侧边栏点击跳转时,右边就要内容区变化,所以我们还需要一个公共的父路由容器来方便展示这些内容信息,定义一个routesData,引入处理路由的方法,将之前处理好的路由信息交给父路由的children,这样当我们点击侧边栏跳转时,就不会跳转到一个新的页面了,而是在当前页面切换不同内容。

function routesData(result){
	constantRouterMap.push({
	path:'/layout',
	redirect: '/',
	component:resolve => require([`@/layout/index`],resolve),
	children:getAsyncRoutes(result)
	})
	return constantRouterMap
}

最后,为了防止刷新页面导致动态路由的信息丢失,需要使用vuex存储当前的数据

vuex文件相关方法

actions.js

const actions={ 
addRoutes(context,routes){
        context.commit('setMenuAndRouter',routes)
    },
}
export default actions

mutations.js

const mutations={
  setMenuAndRouter(state,menus){
    this.state.addRoutes=menus
  },
}

export default mutations

 state.js

const state={
    addRoutes: [],
}

export default state

同时,为了防止刚进页面时是空白页但是url显示正常的问题,我们还需要配合路由前置守卫beforeEach来实现页面的数据加载。

router.beforeEach(async (to,from,next)=>{//路由守卫,路由跳转
    
    let route=await store.state.addRoutes;//获取存在vuex中的路由信息
    const hasRouters=route&&route.length>0;
    if(hasRouters){//判断当前是否已经有路由信息,如果有的话,就放路由往下走
        next()
   }else{//如果路由信息不存在,就获取我们的路由数据,然后存进vuex
       const data=routesData(menu.data)
       store.dispatch("addRoutes",data)//存储当前路由信息    
       router.addRoutes(data)//往现有的路由后面添加新的路由
       next({...to,replace:true});//告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由
   }
})

效果图展示 

 

---------------------------------------------------------------------------------------------------------------------------------

注明:本人菜鸟一枚,第一次做动态路由,遇到了一些坑,百度了很多,做了几天才终于实现,特此将自己的方法展示出来希望能帮到各位,如果哪里不对的还希望各位大神指出,谢谢

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值