Vue-router の path の制限に正規表現を使いたい

vue-router
nuxt

#1

下記 Nuxt のサンプルを使って vue-router redirect を試しています。

Custom Routes
/users/:id という route pattern で user 毎のページに遷移するサンプル

サンプルでは

  • /users/1
  • /users/2
  • /users/3

という path で遷移するのはできますが

/users/1

/users/first

という alias 的な path で遷移できるか試しました。

以下を参考に、

The router Property / extendRoutes

まず /users/first/users 部分を含まない

/first

のみでの遷移を試みました。

nuxt.config.js

export default {
  mode: "spa",

  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        path: "/first",
        redirect: {
          name: "users-id",
          params: { id: 1 }
        }
      });
    }
  }
}

画面上の 1st User をクリックした結果

a

/users/1 のページに遷移しています。正しい。

20190323T133338

続いて以下の path を試すため

/users/first

nuxt.config.js

export default {
  mode: "spa",

  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        name: "users-first",
        path: "/users/first",
        redirect: {
          name: "users-id",
          params: { id: 1 }
        }
      })
    }
  }
}

と書き換えました。

この設定は以下のように反映されます。

.nuxt/router.js

export function createRouter() {
  return new Router({
    ...
    routes: [{
      path: "/users/:id?",
      component: _26f88e7f,
      name: "users-id"
    }, {
      path: "/",
      component: _b31564d6,
      name: "index"
    }, {
      path: "/users/first",
      redirect: {"name":"users-id","params":{"id":1}},
      name: "users-first"
    }],
    ...
  })
}

このまま先程のリンク「1st User」をクリックすると、以下のように失敗します。

20190323T134706

そこで、routers.push ではなく routers.unshift に変更して、評価に使われる regex の順番を変えてみると、

nuxt.config.js

router: {
  extendRoutes(routes, resolve) {
    routes.unshift({

.nuxt/router.js

export function createRouter() {
  return new Router({
    ...
    routes: [{
      path: "/users/first", ................................ (1)
      redirect: {"name":"users-id","params":{"id":1}},
      name: "users-first"
    }, {
      path: "/users/:id?", ................................. (2)
      component: _26f88e7f,
      name: "users-id"
    }, {
      path: "/",
      component: _b31564d6,
      name: "index"
    }],
    ...
  })
}

「1st User」のリンクが /users/first に変更されている。

20190323T135427

この /users/first リンクをクリックすると /users/1 に redirect している。

20190323T135444

redirect に成功します。

routers.push を routers.unshift に変更して成功した理由は、

/users/first の評価において、
上記 (1) で生成される router.regex が
上記 (2) で生成される router.regex よりも先に match するようになったからです。

(2) の regex が先に配置されると、(1) の regex よりも先に /users/first に match してしまいます。

でも、(2) の regex が先に match しないよう /users/:id?id

id: /^[0-9]+$/

と制限できれば良いのですが、その指定方法が分かりません。

以下を読むと、

Dynamic Route Matching / Advanced Matching Patterns

vue-router 内部では以下を使っているそうなんですが、

Path-to-RegExp

Nuxt 内での指定方法が分かりません。そもそも vue-router での指定方法も分かってませんが。

どなたか分かりになる方いらっしゃいませんか?

以下にサンプルを置いています。

codesandbox


#2

nuxt.config.js

export default {
  ...
  router: {
    extendRoutes(routes, resolve) {
      const route = routes.find(route => (route.name == 'users-id'));
      if (route) {
        route.path = route.path.replace(':id?', ':id(\\d+)?'); ....... (3)
      }

      routes.push({
        name: "users-first",
        path: "/users/first",
        redirect: {
          name: "users-id",
          params: { id: 1 }
        }
      })
    }
  }
}

.nuxt/router.js

routes: [{
  path: "/users/:id(\\d+)?",
  component: _26f88e7f,
  name: "users-id"
}, {
  path: "/",
  component: _b31564d6,
  name: "index"
}, {
  path: "/users/first",
  redirect: {"name":"users-id","params":{"id":1}},
  name: "users-first"
}],