DTeam 技术日志

Doer、Delivery、Dream

url 的正则表达式 path-to-regexp 在 Angular 中的使用

纪瑞瑶 Posted at — Jan 6, 2021 阅读

前言

前端有的时候需要对 url 或者 http 请求进行处理,比如有的 api 不需要带 token 访问,有的直接请求第三方接口。之前处理的方式是简单的包含判断,后来发现这样不够严谨也容易出问题。正确的做法是用正则去匹配,但是自己写的也难保不会出错,所以就找了第三方库:path-to-regexp。

什么是 path-to-regexp?

将字符串路径转换为正则表达式的工具。

比如:/user/:id 转换为 /^\/user\/((?:[^\/]+?))(?:\/(?=$))?$/i

这样只需要规定想匹配的api就行了,而不需要花费大量时间去写或者调试正则。

参数

它有三个参数:path,keys,options

path: 传入的url

类型:String, Array, RegExp

keys:追加在 path 中解析到的命名参数

类型:Array

// 传入的 keys 为[1,2],url 中 bar 为参数,会将bar解析出来追加到 keys 中
var keys = [1,2]
var re = pathToRegexp('/foo/:bar', keys)
// re = /^\/foo\/([^\/]+?)\/?$/i
// keys = [1,2,{ name: 'bar', prefix: '/', delimiter: '/', optional: false, repeat: false, pattern: '[^\\/]+?' }]

options: 可设置大小写是否敏感,匹配给定的开头或结尾,编码等

具体可点击 path-to-regexp 查看。

类型:Object

API

  1. pathToRegexp 创建一个pathToRegexp对象。
pathToRegexp("/user/:id");
  1. parse()

解析 url 参数

const params = parse("/user/:id");
console.log(params);
// 打印结果为:
[
 '/user',
  {
    name: 'id',
    prefix: '/',
    delimiter: '/',
    optional: false,
    repeat: false,
    partial: false,
    pattern: '[^\\/]+?'
 } 
]
  1. compile() 填充参数
const toPathRaw = compile("/user/:id");
toPathRaw({ id: 1 })
//  结果为:
// "/user/1"
  1. match() url 匹配
const mm = match("/user/:id", { decode: decodeURIComponent });
console.log(mm("/user")) // false
console.log(mm("/user/123")); // { path: '/user/123', index: 0, params: { id: '123' } }

如果路由字符串是没有经过 url 转义的,则可能导致一些未知的问题,所以在适当的时候,应该考虑对原始的路由串进行 encode 处理。

Angular 使用 path-to-regexp

安装:

npm install path-to-regexp --save

在 angular10 中,Angular CLI 检测到你的浏览器端应用依赖了 CommonJS 模块,就会发出警告,所以需要在 angular.json 文件中 build 区添加 allowedCommonJsDependencies 配置:

"build":  {  
  "builder":  "@angular-devkit/build-angular:browser",  
  "options":  {  
    "allowedCommonJsDependencies":  [  
        "path-to-regexp"  
      ]  ...  
    }  ...  
},

在 ts 文件中引用:

import { pathToRegexp, match, parse, compile } from 'path-to-regexp';
//   需要哪个引入哪个即可

使用 path-to-regexp:

// 不需要登陆
filterUrl = ['login']

// 直接访问第三方
filterNetUrl = ['https', 'http'];

// 判断是否为直接访问第三方接口的api
 this.filterNetUrl.find(fu => {
      const mm = match(fu);
      if(mm(url)) {
      // 处理逻辑
      }
 })

// 判断是否为不需要登陆访问的api
 this.filterUrl.find(fu => {
  const mm = match(`/api/${fu}`);
    if(mm(url)) {
     // 处理逻辑
    }
 })

这样就可以根据不同 api 类型处理不同 http 请求。

总结

path-to-regexp 是一个强大的处理前端路由的工具,对于一些复杂的路由或者判断使用它可以规避很多潜在的问题。


相关文章