登录是获取添加的路由,存在vuex中
login.vue
import {initRoutes} from "@/router/index.js"; // 按需引入路由的动态注入方法
//获取要添加的路由
let navList = [
{
module: "system",
children: [
{
id: 1,
path: "/system/marketTopics",
icon: "icon-shichang",
title: "市场主体专题",
},
{
id: 2,
path: "/system/floorTopics",
icon: "icon-changfang",
title: "楼宇厂房载体专题",
},
{
id: 3,
path: "/system/industryTopics",
icon: "icon-xiangmu",
title: "产业项目专题",
}, {
id: 4,
path: "/system/user",
icon: "el-icon-menu",
title: "用户管理",
},
],
},
{
module: "user",
children: [
{
id: 1,
path: "/user",
icon: "el-icon-menu",
title: "用户管理",
},
],
},
];
// 存在vueX中
this.$store.commit("setNavList", navList);
// 动态添加路由
initRoutes();
vueX代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 动态路由
navList: JSON.parse(window.sessionStorage.getItem('navList') || '[]')
},
mutations: {
// 动态路由
setNavList(state, data) {
state.navList = data;
window.sessionStorage.setItem("navList", JSON.stringify(data));
}
},
actions: {
},
modules: {}
})
router/index.js 路由配置文件代码如下
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'
import Login from '@/views/Login'
import Index from '@/views/Index'
import Error from '@/views/Error'
import NotFound from '@/views/NotFound'
// 数据管理
import System from '@/views/System'
import MarketTopics from '@/views/System/MarketTopics' //市场主体专题
import FloorTopics from '@/views/System/FloorTopics' //楼宇厂房专题
import IndustryTopics from '@/views/System/IndustryTopics' //产业项目专题
import User1 from '@/views/System/User' //用户管理
// 用户管理
import User from '@/views/User'
// 需要动态添加的路由
const marketTopics = { path: '/system/marketTopics', component: MarketTopics }
const floorTopics = { path: '/system/floorTopics', component: FloorTopics }
const industryTopics = { path: '/system/industryTopics', component: IndustryTopics }
const user = { path: '/system/User', component: User1 }
// 动态路由根据名称匹配跳转页面
const ruleMapping = {
'/system/marketTopics': marketTopics,
'/system/floorTopics': floorTopics,
'/system/industryTopics': industryTopics,
'/system/user': user,
};
Vue.use(VueRouter)
// 创建默认路由
const createRouter = () => new VueRouter({
// mode: 'history',
base: '/', // 打包时需要配置访问目录
routes: [{
path: '/',
redirect: "/login"
}, {
path: '/login',
component: Login
}, {
path: '/index',
component: Index,
name:"Index",
}, {
path: '/notFound',
name: 'notFound',
component: NotFound
}, {
// 没有路由的访问权限时,访问的页面404
path: '*',
component: Error
}]
})
const router = createRouter();
/*
路由导航守卫
to 要跳转到哪个界面
from 从哪跳转来的
next 是否要放行
*/
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
// 如果是要跳转登录就直接放行
next()
} else {
// 检查路由元信息,是否开启登录验证
if (to.matched.some(record => record.meta.requiresAuth)) {
const token = store.state.user.token;
// 判断用户是否已经登录
if (!token) {
// 没登陆还是跳转登录页
next('/notFound')
} else {
// 正常情况就放行,设置当前路由地址
window.sessionStorage.setItem('activePath', to.path)
next()
}
} else {
// 没开启登录验证,放行
next()
}
}
});
// 解决 Vue 重复点击相同路由,出现 Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation 问题
const VueRouterPush =VueRouter.prototype.push
VueRouter.prototype.push = function push (to) {
return VueRouterPush.call(this, to).catch(err => err)
}
// 动态导入路由
export function initRoutes() {
const token = store.state.user.token;
if (!token) {
router.login
} else {
const currentRoutes = router.options.routes; // 获取要添加路由的当前路由
const navList = store.state.navList; // 获取state中缓存的根据权限获取的路由
if (navList.length > 0) {
const currentIndex = { path: '/system', component: System, children: [] }
let currentUser = ""
navList.forEach(item => { // 循环获取的路由
if (item.module == "system") {
const list = item.children
const redirect = list[0].path;
currentIndex.redirect = redirect
list.forEach((t, i) => {
const temp = ruleMapping[t.path]; // 获取需要动态添加的路由,对应的跳转页面配置
currentIndex.children.push(temp); // 将匹配的路由,添加到当前路由的对应子路由位置
})
} else if (item.module == "user") {
currentUser = { path: '/user', component: User, children: [] }
currentRoutes.push(currentUser);
}
});
currentRoutes.push(currentIndex);
router.addRoutes(currentRoutes); // 执行动态添加路由方法,完成动态路由添加
}
}
}
// 重置路由(退出登录,切换账号)
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // the relevant part
router.options = newRouter.options;
}
export default router
解决刷新页面路由丢失问题,在APP.vue文件下调用initRoutes
代码如下:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import { initRoutes } from '@/router/index.js'
export default {
created() {
// 生命周期内,刷新时重新动态添加组件,防止刷新后路由丢失
initRoutes()
}
}
</script>
<style>
#app {
height: 100%;
}
</style>
— 优化开始 — --- 优化开始 — --- 优化开始 — --- 优化开始 — --- 优化开始 —
使用动态路由加addRoutes(优化两个文件代码,其他同上)
登录时存入vuex
// 存储权限列表
let navList = [{
module: 'index',
isOnePage: false,
name: '首页',
list: [{
id: 1,
title: '地图首页',
icon: '',
path: '/index/home',
children: []
} ]
}];
if (userObj.type == '1') {// 假设是管理员用户,添加后台管理页面权限
navList[0].list.push({
id: 2,
title: '后台管理',
icon: '',
path: '/index/system',
children: [
{
id: 21,
title: '传染病信息统计',
icon: 'icon-chuanranbingguanli',
path: '/index/system/attack'
},
{
id: 24,
title: '传染病时序数据管理',
icon: 'icon-jiancedianshishijiance',
path: '/index/system/infection'
},
{
id: 23,
title: '监测点信息管理',
icon: 'icon-shujuguanli',
path: '/index/system/survey'
},
{
id: 22,
title: '采样点信息管理',
icon: 'icon-caiyangjilu',
path: '/index/system/sampling'
},
{
id: 25,
title: '模型管理',
icon: 'icon-moxingshezhi',
path: '/index/system/model'
},
{
id: 26,
title: '预警结果',
icon: 'icon-hetongyujing',
path: '/index/system/warnResult'
},
{
id: 10,
title: '用户管理',
icon: 'icon-zhanghaoshenhe',
path: '',
children:[
{
id: 10,
title: '账号管理',
icon: '',
path: '/index/system/user',
},
]
},
]
})
}
this.$store.commit('setNavList', navList);// 存入vuex中(vuex同上)
router.js(添加动态路由,优化initRoutes方法)
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'
const Login = () => import('@/views/Login');
const Error = () => import('@/views/Error');
const NotFound = () => import('@/views/NotFound');
const Index = () => import('@/views/Index');
const Home = () => import('@/views/Home');
const System = () => import('@/views/System');
const Attack = () => import('@/views/System/Attack');
const Infection = () => import('@/views/System/Infection');
const Sampling = () => import('@/views/System/Sampling');
const Model = () => import('@/views/System/Model');
const WarnResult = () => import('@/views/System/WarnResult');
const Survey = () => import('@/views/System/Survey');
const User = () => import('@/views/System/User');
// 需要动态添加的路由
const index = {path: '/index', component: Index}
const home = {path: '/index/home', component: Home}
const system = {path: '/index/system', component: System}
const attack = {path: '/index/system/attack', component: Attack}
const infection = {path: '/index/system/infection', component: Infection}
const sampling = {path: '/index/system/sampling', component: Sampling}
const model = {path: '/index/system/model', component: Model}
const warnResult = {path: '/index/system/warnResult', component: WarnResult}
const survey = {path: '/index/system/survey', component: Survey}
const user = {path: '/index/system/user', component: User}
// 动态路由根据名称匹配跳转页面
const ruleMapping = {
'/index': index,
'/index/home': home,
'/index/system': system,
'/index/system/attack': attack,
'/index/system/infection': infection,
'/index/system/sampling': sampling,
'/index/system/model': model,
'/index/system/warnResult': warnResult,
'/index/system/survey': survey,
'/index/system/user': user,
};
Vue.use(VueRouter)
// 创建默认路由
const createRouter = () => new VueRouter({
// mode: 'history',
base: '/', // 打包时需要配置访问目录
routes: [{
path: '/',
redirect: "/login"
}, {
path: '/login',
component: Login
}, {
path: '/notFound',
name: 'notFound',
component: NotFound
}]
})
const router = createRouter();
/*
路由导航守卫
to 要跳转到哪个界面
from 从哪跳转来的
next 是否要放行
*/
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
// 如果是要跳转登录就直接放行
next()
} else {
// 检查路由元信息,是否开启登录验证
if (to.matched.some(record => record.meta.requiresAuth)) {
const token = store.state.user.token;
// 判断用户是否已经登录
if (!token) {
// 没登陆还是跳转登录页
next('/notFound')
} else {
// 正常情况就放行,设置当前路由地址
window.sessionStorage.setItem('activePath', to.path)
next()
}
} else {
// 没开启登录验证,放行
next()
}
}
});
// 动态导入路由
export function initRoutes() {
const token = store.state.user.token;
if (!token) {
router.login
} else {
const currentRoutes = router.options.routes; // 获取要添加路由的当前路由
const navList = store.state.navList; // 获取state中缓存的根据权限获取的路由
navList.forEach(item => { // 循环获取的路由
// 不是单页
// 首先获取模块第一个路由的地址,配置模块默认访问页面
let firstPath = ""
if (item.list && item.list.length > 0) {
firstPath = item.list[0].path;
if (firstPath === '' || firstPath == null) {
firstPath = item.list[0].children[0].path;
}
}
let currentIndex = {
path: `/${item.module}`,
component: ruleMapping[`/${item.module}`].component,
meta: {
requiresAuth: true
},
redirect: firstPath,
children: []
};
currentRoutes.splice(1, 0, currentIndex);
currentRoutes.push({//push 404页面,解决刷新后404闪现问题
// 没有路由的访问权限时,访问的页面404
path: '*',
component: Error
})
// 循环添加子页面路由
if (item.list && item.list.length > 0) {
item.list.forEach(item2 => { // 循环获取的路由
let temp = ruleMapping[item2.path]; // 获取需要动态添加的路由,对应的跳转页面配置
let childrenArr = []
if (item2.children.length > 0) {
item2.children.forEach(item3 => {
if (item3.path === '' || item3.path == null) {
item3.children.forEach(item4 => {
let temp = ruleMapping[item4.path]; // 获取需要动态添加的路由,对应的跳转页面配置
childrenArr.push(temp); // 将匹配的路由,添加到当前路由的对应子路由位置
});
} else {
let temp = ruleMapping[item3.path]; // 获取需要动态添加的路由,对应的跳转页面配置
childrenArr.push(temp); // 将匹配的路由,添加到当前路由的对应子路由位置
}
});
}
temp["children"] = childrenArr; // 将匹配的路由,添加到当前路由的对应子路由位置
temp["redirect"] = childrenArr[0]
currentIndex.children.push(temp); // 将匹配的路由,添加到当前路由的对应子路由位置
});
}
});
router.addRoutes(currentRoutes); // 执行动态添加路由方法,完成动态路由添加
}
}
// 重置路由(退出登录,切换账号)
export function resetRouter() {
const newRouter = createRouter();
router.matcher = newRouter.matcher; // the relevant part
router.options = newRouter.options;
}
export default router
— 优化结束 — --- 优化结束 — --- 优化结束 — --- 优化结束 — --- 优化结束 —