Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Router - catch all wildcard not working

I'm using Vue Router with Vue 3 and am trying to add a catch-all route to redirect the user if they try and access an invalid URL. When I try and use the wildcard (*), i get the following error logged to the console:

Uncaught Error: A non-empty path must start with "/"
    at tokenizePath (vue-router.esm.js?8c4f:975)
    at createRouteRecordMatcher (vue-router.esm.js?8c4f:1106)
    at addRoute (vue-router.esm.js?8c4f:1190)
    at eval (vue-router.esm.js?8c4f:1335)
    at Array.forEach (<anonymous>)
    at createRouterMatcher (vue-router.esm.js?8c4f:1335)
    at createRouter (vue-router.esm.js?8c4f:2064)
    at eval (index.js?a18c:26)
    at Module../src/router/index.js (app.js:1402)
    at __webpack_require__ (app.js:854)

I'm assuming this is because I don't prepend the path containing the asterisk with a '/', but if I do this then the catch all doesn't work. Here are my routes:

imports...

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/user',
    name: 'User',
    // route level code-splitting
    // this generates a separate chunk (user.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "user" */ '../views/user/User.vue'),
    children: [{path: '', component: UserStart}, {path: ':id', component: UserDetail}, {path: ':id/edit', component: UserEdit, name: 'userEdit'}]
  },
  {path: '/redirect-me', redirect: '/user'},
  {path: '*', redirect: '/'}
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

The wildcard route is the last object in the routes array. Does anyone know what I'm doing wrong?

like image 465
user14131782 Avatar asked Aug 21 '20 16:08

user14131782


2 Answers

Catch all routes (/*) must now be defined using a parameter with a custom regex: /:catchAll(.*)

For example:

    {
      // path: "*",
      path: "/:catchAll(.*)",
      name: "NotFound",
      component: PageNotFound,
      meta: {
        requiresAuth: false
      }
    }
like image 118
Raj Avatar answered Nov 12 '22 06:11

Raj


Personally, for Vue 2's * (star or catch all) routes in Vue 3 I use:

{
  path: '/:pathMatch(.*)*', <== THIS
  name: 'not-found',
  component: NotFound
}

Catch all routes (*, /*) must now be defined using a parameter with a custom regex:

The parameter name can be whatever you want like catchAll, pathMatch, noPage etc

{
  path: '/:pathMatch(.*)*', //will match everything and put it under `$route.params.pathMatch`
  name: 'not-found',
  component: NotFound
}
{ 
  path: '/user-:afterUser(.*)',// will match anything starting with `/user-` and put it under `$route.params.afterUser`
  component: UserGeneric
}


/:pathMatch(.*)*

  • The last * it is necessary if you plan on directly navigating to the not-found route using its name.

  • If you omit it the / character in params, it will be encoded when resolving or pushing.

For example if you use path: /:pathMatch(.*) (note: without the last asterisk) and you go to /user/not-found (a page that doesn't exists) the this.$route.params.pathMatch will be a string => 'user/not-found'

// bad example if using named routes:
router.resolve({
  name: 'bad-not-found',
  params: { pathMatch: 'not/found' },
}).href // '/not%2Ffound'

Instead, if you use path: /:pathMatch(.*)* (note: with asterisk) this.$route.params.pathMatch will be an array ['user', 'not-found']

// good example:
router.resolve({
  name: 'not-found',
  params: { pathMatch: ['not', 'found'] },
}).href // '/not/found'

Please read docs: From migration from vue 2 to vue 3 and Catch all / 404 Not found Route

like image 16
Roland Avatar answered Nov 12 '22 06:11

Roland