当动态参数路由遇上通配符匹配路由,通配符匹配路由可能会失效。

最近在重开前端,所以在重新学习 VueRouter,但在学习的过程中,我发现了个问题:

大致情况

当动态参数路由 A 和通配符匹配路由 B,是这样的关系时,通配符匹配路由 B 可能会失效。
具体的情况/条件是:

  1. 当动态参数路由 A 和通配符匹配路由 B,路由 A 的 path 为 /a/:id,通配符匹配路由 B 的 path 为 /a/* (或是 /a/content-*)

  2. 且上述两个路由配置是在 routes 这个数组对象的同一级。此情况目前有两种:

    1. 默认的路由,即 routes 数组中的两个路由配置是在同一级。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      const routes = [
      //.....
      {
      path: '/a/:id' // 路由 A
      // ......
      },
      {
      path: '/a/*' // 路由 B
      // ......
      }
      // ......
      ]
    2. 有嵌套路由,且这两类型的路由处于同一个 children 属性(嵌套路由)下。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      const routes = [
      //.....
      {
      path: '/xxxx'
      // ......
      },
      {
      path: '/a',
      // ......
      children: [
      {
      path: ':id' // 路由 A
      // ......
      },
      {
      path: 'content-*' // 路由 B
      // ......
      }
      // ......
      ]
      }
      // ......
      ]

在上述情形下,通配符匹配路由 B 配置会失效。无法正常匹配到预定的组件。只会匹配到路由 A 的组件。

在几番尝试和推理后发现,这个问题的根本原因是:

动态参数路由的集合范围在代码/数学逻辑上是大于等于通配符路由的集合范围的。

而路由的每次跳转,都会遍历一边 routes 这个路由数组对象,找到匹配的路由配置,然后匹配到相应的组件。

假如动态参数路由在通配符路由之前的话,那么会优先命中动态参数路由,而不会命中通配符路由。

亦可参考匹配优先级中所说的:

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:路由定义得越早,优先级就越高。

如何解决这个问题?

为了避免这种情况,就需要将通配符路由放置在动态参数路由之前。