微人事 vue-roter4实现动态加载路由,解决[Vue Roter warn]: No match found for location with path “xxx“

一:解决初次加载子菜单报错 No match found for location with path “xxx”

最近在做微型人事项目,进行到左边导航菜单动态加载部分,前端所有的子项都无法打开
在这里插入图片描述
以基本资料为例,点击会在控制台弹出如下警告信息:
在这里插入图片描述
教程中src/utils/menus.js内的initMenu方法从后台请求得到动态的菜单栏数据data,使用formatRoutes方法将data中的“component”对应的字符串数据转化为.vue组件。
教程代码:

import {getRequest} from "./api";

export const initMenu = (router, store) => {
    if (store.state.routes.length > 0) {
        return;
    }
    getRequest("/system/config/menu").then(data => {
        if (data) {
            var str1 = JSON.stringify(data)
            console.log("data:"+str1)
            let fmtRoutes = formatRoutes(data);
            console.log("fmtRoutes:"+JSON.stringify(fmtRoutes))
            router.addRoutes(fmtRoutes)
            console.log("所有:"+JSON.stringify(router.options.routes))
            store.commit('initRoutes', fmtRoutes);
        }
    })
}
export const formatRoutes = (routes) => {
    let fmRoutes = [];
    routes.forEach(router => {
        let {
            path,
            component,
            name,
            meta,
            iconCls,
            children
        } = router;
        if (children && children instanceof Array) {
            children = formatRoutes(children);
        }
        let fmRouter = {
            path: path,
            name: name,
            iconCls: iconCls,
            meta: meta,
            children: children,
            component(resolve) {
                if (component.startsWith("Home")) {
                    require(['../views/' + component + '.vue'], resolve);
                } else if (component.startsWith("Emp")) {
                    require(['../views/emp/' + component + '.vue'], resolve);
                } else if (component.startsWith("Per")) {
                    require(['../views/per/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sal")) {
                    require(['../views/sal/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sta")) {
                    require(['../views/sta/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sys")) {
                    require(['../views/sys/' + component + '.vue'], resolve);https://next.router.vuejs.org/zh/guide/advanced/dynamic-routing.html
                }
            }
        }
        fmRoutes.push(fmRouter);
    })
    return fmRoutes;
}

①:使用router.addRoute()代替router.addRoutes()

教程中使用的是vue2(vue router3)而我目前的环境是vue3(vue router3),教程中使用router.addRoutes(fmtRoutes)将处理过的后台数据加到router内,查看router.addRoutes动态路由可以知道目前router.addRoutes()已经被router.addRoute()代替,目前不能一次性添加多条路由规则,而是一次添加一条。
于是计划遍历fmtRoutes然后用router.addRoute()挨个存入·。

	fmtRoutes.forEach(t => {
	   router.addRoute(t)
	           })

但修改完后还是报错,报错信息如下:
在这里插入图片描述
在这里插入图片描述

②:修改组件引入方式

component(resolve) {...}这块代码的主要作用是根据不同的component开头名字引入不同目录下的.vue文件,怀疑是require这种引入方式有问题,于是改成import,最终component(){...}代码块如下:

            component() {
                if (component.startsWith("Home")) {
                    return import('../views/' + component );
                } else if (component.startsWith("Emp")) {
                    return import('../views/emp/' + component);
                } else if (component.startsWith("Per")) {
                    return import('../views/per/' + component);
                } else if (component.startsWith("Sal")) {
                    return import('../views/sal/' + component);
                } else if (component.startsWith("Sta")) {
                    return import('../views/sta/' + component);
                } else if (component.startsWith("Sys")) {
                    return import('../views/sys/' + component);
                }
            }

测试:
发现员工资料下的基本资料不能正常访问(以admin账户登录),其他菜单的子项都能访问。
在这里插入图片描述
如:人事管理下的员工资料就可以正常访问
在这里插入图片描述
查看后端返回的json

[
    {
        "id": 2,
        "url": "/",
        "path": "/home",
        "component": "Home",
        "name": "员工资料",
        "iconCls": "fa fa-user-circle-o",
        "meta": {
            "keepAlive": null,
            "requireAuth": true
        },
        "parentId": 1,
        "enabled": true,
        "children": [
            {
                "id": 7,
                "url": null,
                "path": "/emp/basic",
                "component": "EmpBasic",
                "name": "基本资料",
                "iconCls": null,
                "meta": {
                    "keepAlive": null,
                    "requireAuth": true
                },
                "parentId": 2,
                "enabled": true,
                "children": null
            }
        ]
    },...

员工资料下的基本资料是存在的,而且component值为"EmpBasic"
于是把经过处理的后台数据fmtRoutes遍历,输出到控制台。

        fmtRoutes.forEach(t => {
            console.log("t:"+JSON.stringify(t))
            router.addRoute(t)
        })

在这里插入图片描述
可以看出第一个员工资料存在子项基本资料
那么问题可能在router.addRoute(t)这个过程中,用router.getRoutes()查看router加入数据之后的信息,在控制台输出。

            fmtRoutes.forEach(t => {
                console.log("t:"+JSON.stringify(t))
                router.addRoute(t)
            })
            console.log(router.getRoutes())

在这里插入图片描述

③:修改路由中重复的name值

从上图可知只存在一个name为员工资料的路由,而且path'/per/emp',怀疑是router不允许name值重复,于是在数据库中将该name值改成员工信息
测试:
在这里插入图片描述
访问正常!

二:解决在某一个子菜单页刷新,报错 No match found for location with path “xxx”

当我们解决完第一个问题时,会发现:虽然所有子菜单项目都能正常访问,但是在当前子菜单项点击刷新后,会显示空白页面,控制台继续报错No match found for location with path "xxx",以员工资料下的基本资料为例:
在这里插入图片描述
查看控制台,可以看到Vue Roter在一开始就被调用了,而component得在之后才能引入,自然就找不到了,参考next({…to, replace: true})的作用,(确保动态路由完全加载)修改代码:

①修改menus.js/initMenu方法

修改前:

export const initMenu = (router, store) => {

    if (store.state.routes.length > 0) {
        return;
    }
    getRequest("/system/config/menu").then(data => {
        if (data) {
            let fmtRoutes = formatRoutes(data);
            store.commit('initRoutes',fmtRoutes);
            fmtRoutes.forEach(t => {
                router.addRoute(t)
            })
            console.log(router.getRoutes())
        }
    })
}

修改后:

export const initMenu=(router, store,next)=>{

    if(store.state.routes == 0) {
    getRequest("/system/config/menu").then(data=>{
        if(data) {
            let fmtRoutes = formatRoutes(data);
            store.commit('initRoutes',fmtRoutes);
            fmtRoutes.forEach(t => {
                router.addRoute(t)
            })
            next({...to, replace: true})
            console.log(router.getRoutes())
        }
    })
    } else {
        next();
    }
}

②将menus.js/initMenu方法的实现移动到main.js/router.beforeEach(){…}内部,确保next({…to, replace: true})运行

修改前:

router.beforeEach((to, from,next) => {

    if (to.path == '/') {
        next();
    }else {
        if(window.sessionStorage.getItem("user")) {
        initMenu(router, store);
        next();
        } else {
            next('/?redirect='+to.path)
        }
    }
})

修改后:

router.beforeEach((to, from,next) => {

    if (to.path == '/') {
        next();
    }else {
        if(window.sessionStorage.getItem("user")) {
            if(store.state.routes == 0) {
                getRequest("/system/config/menu").then(data=>{
                    if(data) {
                        let fmtRoutes = formatRoutes(data);
                        store.commit('initRoutes',fmtRoutes);
                        fmtRoutes.forEach(t => {
                            console.log("t:"+JSON.stringify(t))
                            router.addRoute(t)
                        })
                        next({...to, replace: true})
                    }
                })
            } else {
                next();
            }
        } else {
            next('/?redirect='+to.path)
        }
    }
})

测试:刷新正常显示。
在这里插入图片描述
前端项目仓库:人事管理(前端)

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
当出现"[Vue Router warn]: No match found for location with path "/" "这个警告时,它意味着当前路由中没有与该路径匹配的路由。这通常是因为刷新浏览器时,动态路由尚未加载的原因。为了解决这个问题,我们可以采取以下两个步骤: 步骤1:在router/index.js文件中,我们可以添加一个临时路由来处理当前路径的匹配问题。具体做法是: const { name } = router.currentRoute.value if (!name) { router.addRoute({ path: window.location.pathname, name: 'TempRoute', component: () => import('@/components/layouts/emptyLayout.vue') }) } 这样,在刷新浏览器时,就会在路由中添加一个临时的路由来匹配当前路径。 步骤2: 确保在导出router实例之前,将临时路由添加到路由中。例如: export default router 通过以上两个步骤,我们可以解决"[Vue Router warn]: No match found for location with path "/" "这个警告,并且在刷新浏览器时正确地匹配相关的路由。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue3 addRoute 动态路由 页面刷新后 路由失效 [Vue Router warn]: No match found for location with path](https://blog.csdn.net/weixin_43835425/article/details/116708448)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [解决Vue3.0 页面刷新 [Vue Router warn]: No match found for location with path 警告](https://blog.csdn.net/maoeye283301717/article/details/126482974)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值