模拟后台接口数据
{
"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本次操作后,不能通过浏览器后退按钮,返回前一个路由
}
})
效果图展示
---------------------------------------------------------------------------------------------------------------------------------
注明:本人菜鸟一枚,第一次做动态路由,遇到了一些坑,百度了很多,做了几天才终于实现,特此将自己的方法展示出来希望能帮到各位,如果哪里不对的还希望各位大神指出,谢谢