vue-router解决警告:No match found for location with path "XXXXXXX"

发布时间 2023-04-21 19:55:27作者: 没有星星的夏季

  使用vue-router时,在刷新页面时往往会出现这个警告:

  

  这个问题产生的原因往往是因为vue在启动时,会校验当前页面的路由,而我们使用vue-router时,是在导航守卫中动态添加路由的,因此肯定找不到,而这个时候还没进入守卫,自然就会抛出这个警告了:  

    1、app.use(router)
    2、router.install(app)
    3、push(routerHistory.location)
    4、pushWithRedirect(to)
    5、resolve(to)

  resolve函数部分代码如下:  

    function resolve(rawLocation, currentLocation) {
        // const objectLocation = routerLocationAsObject(rawLocation)
        // we create a copy to modify it later
        currentLocation = assign({}, currentLocation || currentRoute.value);
        if (typeof rawLocation === 'string') {
            const locationNormalized = parseURL(parseQuery$1, rawLocation, currentLocation.path);
            const matchedRoute = matcher.resolve({ path: locationNormalized.path }, currentLocation);
            const href = routerHistory.createHref(locationNormalized.fullPath);
            if ((process.env.NODE_ENV !== 'production')) {
                if (href.startsWith('//'))
                    warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`);
                else if (!matchedRoute.matched.length) {
                    warn(`No match found for location with path "${rawLocation}"`);
                }
            }
            // locationNormalized is always a new object
            return assign(locationNormalized, matchedRoute, {
                params: decodeParams(matchedRoute.params),
                hash: decode(locationNormalized.hash),
                redirectedFrom: undefined,
                href,
            });
        }
        
        //省略...
    }

  其中rawLocation就是routerHistory.location,其实就是location.pathname+location.search+location.hash,因为路由是在守卫中动态添加的,这里matcher.resolve自然就匹配不到路由了,因为此时项目才启动,还没进入守卫中。

  虽然这个可能不会对我们的功能有什么大的影响,但是我们还是可以从根本上处理掉它,让我们应用更加完善。

  解决办法

  这个问题的一个解决思路:  

    1、创建router时,添加一个全局的路由,一般可以取名为404,表示没有匹配到路由
    2、当页面刷新时,resolve函数中matcher.resolve未匹配到正确路由时,就会匹配到这个404的路由
    3、因为有匹配到路由,所以就不会有警告,接着进入守卫
    4、在守卫中从后端获取数据,动态构建路由
    5、然后对404路由的路由进行重定向

  1、添加404路由:  

  // 静态路由
  export const constantRouterMap = [
    {
      name: 'root',
      path: '/',
      redirect: '/welcome',
      component: AppLayout,
      children: [
        {
          path: 'welcome',
          name: 'welcome',
          component: () => import(`@/views/welcome/index.vue`),
          meta: {
            title: 'Welcome'
          }
        }
      ]
    },
    {
      name: '404',
      path: '/:catchAll(.*)',
      component: () => import(`@/views/error/404.vue`)
    }
  ]
  
  const router = createRouter({
  	history: createWebHistory(process.env.BASE_URL),
  	routes: constantRouterMap
  })

  2、守卫中假如判断  

  // 进入路由前的过滤器
  router.beforeEach((to, from, next) => {
  
    //省略其它代码...
  
    //判断是否登录
    const token = getToken()
    if (token) {
      const routes = getRoutes()
      //路由是否存在
      if (!routes) {
        //不存在则从远程获取
        getUserInfo().then(res => {
          //创建路由routes
  
          // 动态添加可访问路由表
          routes.forEach(r => {
            router.addRoute(r)
          })
  
          //表示要做一次重定向
          if (to.name === '404') {
            next({ path: to.path, query: to.query })
          } else {
            // 请求带有 redirect 重定向时,登录自动重定向到该地址
            if (from.query.redirect) {
              const redirect = decodeURIComponent(from.query.redirect)
              next({ path: redirect })
            } else {
              next({ ...to, replace: true })
            }
          }
  
          //省略其它代码...
        })
      } else { //存在则跳过
  
        //省略其它代码...
  
        next()
      }
    } else {
      next({ name: 'login', query: { redirect: to.fullPath } })
    }
    
    //省略其它代码...
  })

   这样,刷新页面警告也不会出现了