你可能没用过的,VueRouter高级匹配模式

3,143 阅读3分钟

写在前面

vue-router 使用 path-to-regexp作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的文档学习高阶的路径匹配,还有这个例子展示 vue-router 怎么使用这类匹配。——引用自官网

附上AntDesignVuePro这个开源项目中的路由配置示例,该配置比较符合路由非常多的复杂项目的开发实际,所以拿来当个示例,后面讲到的内容,大多参考这里,有兴趣的朋友可以好好研究下。

所谓站在巨人的肩膀上,VueRouter使用这个模块作为路径匹配引擎。path属性作为路由核心属性之一,我们有必要仔细了解一下其匹配机制,以便我们在路由设计上更加得心应手。

本文抛砖引玉,详细用法请自行参考相关链接,文章中如有描述不清楚的地方,欢迎评论指出。

参数限定

利用path-to-regexp提供的能力,可以很好的限制路径,做到精准匹配。

const RouterView = { render: h => h('router-view') }

const typeLimit = 'image|text|video|audio'

const route = {
  path: 'package',
  component: RouterView,
  children: [
    {
      // 通过正则限定type为素材类型,id是数字。若不满足则不会命中
      path: `:type(${typeLimit})/:id(\\d+)`, // ①
      meta: { name: '素材包详情' },
      component: /*对应组件*/,
    },
    {
      path: `:type(${typeLimit})`, // ②
      meta: { name: '素材包列表' },
      component: /*对应组件*/,
    },
  ]
}

// 命中示例
const hits = [
  'package/text', // 命中②,文本素材包列表
  'package/text/1316 ', // 命中①,素材包1316的详情页面
  'package/text/abc', // 未命中,因为①中:id参数(abc)不是数字
  'package/material', // 未命中,因为②中:type参数(material)不属于素材类型
]

从上面的示例中可以看出,在经过正则限定之后,但凡匹配到了对应的路由,那么其参数一定在预料之中,换句话说,package/:type(${typeLimit})路径中拿到的$route.params.type一定是四种类型之一。

通过不同的参数限定,我们还可以实现一个路径,多个路由的效果,例如material/:type(${typeLimit})material/editmaterial/create,这都是常规操作了。

而在以往配置中我们基本上一个路径对应一个页面,package/:type路径只要符合基本结构就能匹配上,其中的type参数可能并不是我们想要的类型,如package/material,但由于结构符合条件,仍会匹配上,这显然不符合预期,因为type参数类型错误,如果是常规匹配,这将可能会造成一些异常。但如果是高级匹配,则不用担心。

同时需要注意VueRouter的路由匹配的优先级——越靠前的路由优先级越高,如果一个路径同时符合多条路由,则会优先匹配靠前的路由。当然,实际使用中慎用,因为可能会造成bug,最好通过参数限定的方式使得路由变得相对唯一。

倘若我们配置了404通配路由,那么未匹配的路由均会指向404页面,整个过程合情合理。

从此世上再无多余的路由...

路由组件透传

细心的伙伴可能已经注意到了,在上面的例子中,用到了一个非常简单的组件RouterView。受AntDesignVuePro这个开源项目的启发,这个组件虽然简单,却很巧妙和实用。这样处理,使得子路由不必局限在同一个父组件下,适用于子路由逻辑独立不共享布局的场景。

还是用上面提到的三个路由material/:type(${typeLimit})material/editmaterial/create来举例。其中editcreate是同一个页面的不同状态,但material/:type(${typeLimit})代表了对应的素材列表,editcreate的素材将会展示在素材列表中。很明显,编辑页面的逻辑和布局不同于展示页面,但他们又有着一些联系,很适合写在一起集中管理。

其他

写了这么久项目,最常用的东西,自己竟没搞懂。笔者也是在做需求的过程中发现,项目路由管理非常混乱,并且命名夹杂大小写、下划线等符号。

再加上项目隶属于微前端子应用,路径本身已经嵌套了一个非常长的前缀,如果项目自身的路劲过长,雪上加霜,那真的不要太酸爽。

为了简化路径,不得不做出改变,而我也是在解决问题的过程中,仔仔细细查找了官方文档才发现这个宝藏用法,分享出来希望能帮助大家规范、优雅地配置自己项目的路由。

传送门

VueRouter高级匹配模式 path-to-regexp AntDesignVuePro 路由配置示例