一、动态路由用到文件如图
二、配置静态文件(router/index.js)
如图:
代码如下:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// 配置项目中没有涉及权限的公共路由
export const constantRoutes = [
{ path: '/', redirect: '/login',
meta: {
title: "登录",
show: false,
}
},
{
path: "/login",
name: "Login",
component: () => import('../views/Login/Index.vue'),
meta: {
title: "登录",
show: false,
}
},
]
const createRouter = () => new Router({
// mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
// 解决相同路径跳转报错.push
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
export default router
三、设置导航守卫(beforeEach)
如图:
代码如下:
import router from './index'
import store from '../store'
router.beforeEach(async (to, from, next) => {
document.title = to.meta.title;
// 获取用户token,用来判断当前用户是否登录
if (localStorage.getItem("token")) {
if (to.path === '/login') {
next({ path: '/home/orderManagement' })
}
//判断store中是否有路由,若有,进行下一步
if ( store.state.addRouters.length>0 ) {
next()
} else {
//store中没有路由,则需要获取获取异步路由,并进行格式化处理
const accessRoutes = await store.dispatch('GenerateRoutes')
await router.addRoutes(accessRoutes);
console.log('accessRoutes: ', accessRoutes)
next({ ...to, replace: true })
}
} else {
if (to.path !== '/login') {
next({ path: '/login' })
} else {
next()
}
}
})
router.afterEach(() => { })
四、将permission.js文件引入main中如图:
五、获取后台权限数据(store/index.js)如图:
代码如下:
GenerateRoutes({ commit }) {
return new Promise(resolve => {
request("/getRouters", {
method: "get",
}).then(res => {
if(res.data){
const addRouters = getAsyncRoutes(res.data)
console.log('object:::',addRouters)
commit('SET_ROUTES',addRouters)
let addRoutersFinsh = []
let mainFrame = {
path: '/home',
name: 'Home',
redirect: "/home/orderManagement",
component: () => import('@/views/Main/Frame.vue'),
meta: {
title: "主页",
show: false,
},
children: []
}
addRouters.forEach((item) => {
mainFrame.children.push(item)
});
addRoutersFinsh.push(mainFrame)
resolve([...constantRoutes,...addRoutersFinsh])
}
})
})
},
六、获取后台数据接口方法(request/index.js)如图:
七、后台数据处理公用方法(utils/asyncRouter.js)如图:
代码如下:
// 引入路由文件这种的公共路由
// Layout 组件是项目中的主页面,切换路由时,仅切换Layout中的组件
// import Layout from '@/layout';
export function getAsyncRoutes(routes) {
const res = []
// 定义路由中需要的自定名
const keys = ['path', 'name', 'children', 'redirect', 'meta', 'hidden']
// 遍历路由数组去重组可用的路由
routes.forEach(item => {
const newItem = {};
switch (item.path) {
case 'home': {
newItem.component = resolve => require(["@/views/Main/Frame.vue"],resolve)
// newItem.component = (() => import(`@/views/Main/Frame.vue`))
newItem.meta = {title: "首页",show: true}
break;
}
case 'orderManagement': {
newItem.component = resolve => require(["@/views/Product/Shebeileixingguanli.vue"],resolve)
// newItem.component = (() => import(`@/views/Product/Shebeileixingguanli.vue`))
newItem.meta = {title: "订单管理",show: true}
break;
}
case 'bujianchanpinkudetail': {
newItem.component = resolve => require(["@/views/Product/pop-up.vue"],resolve)
// newItem.component = (() => import(`@/views/Product/pop-up.vue`))
newItem.meta = {title: "物流管理详情",show: true}
break;
}
case 'Particulars': {
newItem.component = resolve => require(["@/views/Product/Particulars.vue"],resolve)
// newItem.component = (() => import(`@/views/Product/Particulars.vue`))
newItem.meta = {title: "详情",show: true}
break;
}
case 'dataStatistics': {
newItem.component = resolve => require(["@/views/Bujianguanli/Index.vue"],resolve)
// newItem.component = (() => import(`@/views/Bujianguanli/Index.vue`))
newItem.meta = {title: "订单统计",show: true}
break;
}
case 'collectionStatistics': {
newItem.component = resolve => require(["@/views/Bujianguanli/Bujiantongji.vue"],resolve)
// newItem.component = (() => import(`@/views/Bujianguanli/Bujiantongji.vue`))
newItem.meta = {title: "计收统计",show: true}
break;
}
case 'orderStatistics': {
newItem.component = resolve => require(["@/views/Bujianguanli/Bujianguanli.vue"],resolve)
// newItem.component = (() => import(`@/views/Bujianguanli/Bujianguanli.vue`))
newItem.meta = {title: "订单统计",show: true}
break;
}
case 'messageRemind': {
newItem.component = resolve => require(["@/views/DataManage/YuanShuJus.vue"],resolve)
// newItem.component = (() => import(`@/views/DataManage/YuanShuJus.vue`))
newItem.meta = {title: "消息提醒",show: true}
break;
}
case 'authority': {
newItem.component = resolve => require(["@/views/Juesequanxianguanli/Index.vue"],resolve)
// newItem.component = (() => import(`@/views/Juesequanxianguanli/Index.vue`))
newItem.meta = {title: "权限管理",show: true}
break;
}
case 'user': {
newItem.component = resolve => require(["@/views/Juesequanxianguanli/Yonghuguanli.vue"],resolve)
// newItem.component = (() => import(`@/views/Juesequanxianguanli/Yonghuguanli.vue`))
newItem.meta = {title: "账号管理",show: true}
break;
}
case 'role': {
newItem.component = resolve => require(["@/views/Juesequanxianguanli/Jueseguanli.vue"],resolve)
// newItem.component = (() => import(`@/views/Juesequanxianguanli/Jueseguanli.vue`))
newItem.meta = {title: "角色管理",show: true}
break;
}
default:
break;
}
// if (item.component) {
// // 判断 item.component 是否等于 'Layout',若是则直接替换成引入的 Layout 组件
// if (item.component === 'Layout') {
// newItem.component = Layout
// } else {
// // item.component 不等于 'Layout',则说明它是组件路径地址,因此直接替换成路由引入的方法
// newItem.component = resolve => require([`@/views/${item.component}`],resolve)
// // 此处用reqiure比较好,import引入变量会有各种莫名的错误
// // newItem.component = (() => import(`@/views/${item.component}`));
// }
// }
for (const key in item) {
if (keys.includes(key)) {
newItem[key] = item[key]
}
}
// 若遍历的当前路由存在子路由,需要对子路由进行递归遍历
if (newItem.children && newItem.children.length) {
newItem.children = getAsyncRoutes(item.children)
}
res.push(newItem)
})
// 返回处理好且可用的路由数组
return res
} 至此动态路由结束!!!!
八、左侧菜单根据后台返回值显示(主框架Main/Frame.vue)如图:
九、退出登录需清空后台返回的数据,不然permission.js文件中不走const accessRoutes = await store.dispatch('GenerateRoutes')方法,如图: