使用addRoutes动态添加路由

本文介绍了如何在Vue.js应用中实现动态路由配置,包括从 vuex 存储中获取权限列表,根据权限动态添加路由,并处理页面刷新后路由丢失的问题。通过在登录时将权限列表存储到 vuex,然后在路由配置文件中动态生成并添加路由。同时,优化了动态路由的添加方式,实现了更灵活的权限管理和路由管理。在遇到刷新导致的路由丢失时,于APP.vue中调用initRoutes()进行重新加载,确保动态路由生效。
摘要由CSDN通过智能技术生成

登录是获取添加的路由,存在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

— 优化结束 — --- 优化结束 — --- 优化结束 — --- 优化结束 — --- 优化结束 —

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值