前言
随着前端单页面应用的流行和复杂性的增加,前端开发需求的变化和对性能和用户体验的追求,前端开发者开始更多的关注和利用后端语言和工具协同处理。其中,前端到后端的请求和响应,其中最重要的是 url 路径的解析与处理。该路径解析和处理的主要技术是路由。
Koa 是一款基于 Node.js 平台的下一代 web 开发框架,也是时下前端框架中的重要一员。其在路由处理上,同样也有着很多值得我们一探的地方。
什么是路由
路由是一个 web 框架的基础,用于定义特定的 url 去响应请求。它将请求的 url 映射到指定的回调函数上。在路由处理当中,有两个重要的概念是“路由”和“路由器”。“路由”用于表述单个 url 和对应的处理函数,而“路由器”则是建立多个路由和执行路由的机制。
koa-router 的实现方式
Koa 官方推荐的路由处理第三方中间件是“koa-router”。这个库本身非常的轻量级,只含有 390 行的代码,但却制作精良,功能强大。接下来,我们主要看一下 koa-router 是怎么实现的。
实现一:正则表达式匹配路由
koa-router 采用的实现方式是利用正则表达式来匹配路由。其基本思路是将 url 路径进行解析成正则表达式,再用正则表达式来匹配路由,从而达到与处理 url 请求的目的。
例如,以下的示例代码,定义了任意请求方法的根路由,其代码实现如下:
router.all('/', (ctx, next) => { // 处理根路由请求 });
在 koa-router 内部,会将该 url 路径转化成了以下代码的正则表达式进行路由匹配:
/^\/?(?=\/|$)/i
可以看到,这个正则表达式的含义是:
^\/?
: 匹配 url 以 / 开头或不以 / 开头的情况。(?=\/|$)
: 匹配接下来的字符是 / 还是 PATH,如果是 / 就结束匹配,否则匹配到结束。
实现二:树节点搜索路由
另外一种 koa-router 的实现方式是,将路由按照 / 拆分成多个节点,将节点转化成“前缀树”(Trie),然后根据每个 url 部分的路径节点构建树结构来匹配路由。
koa-router 实现的类似前缀树的树结构,内部是基于 hash 的对象来存储每个路径的子节点和路径处理函数,数据结构如下:
{ "path":{ "path":{ "path":{ "path":{ "methods":{ "all":[Function] }, "stack":[ ... ] }, "methods":{ "get":[Function], "post":[Function] } } } } }
该数据结构实现的路由匹配处理过程如下:
// 获取路由前缀树 const router = new Router(); router.get('/user/:id', (ctx, next) => {}); const tree = router.stack.reduce((acc, layer) => { const routerPath = layer.path; const methodsObj = layer.methods; if (methodsObj) { Object.keys(methodsObj).forEach((method) => { if (!acc[method]) { acc[method] = {}; } acc[method][routerPath] = layer; }); } return acc; }, {}); // 加入前缀树的节点判断 const match_router = function (uri, tree) { let uris = uri.split('/').filter(i => i) let recent = null; let node = tree; while (node) { let part = uris.shift() || '/' if (node[part] !== undefined) { node = node[part]; if (!uris.length) { return node; } } else if (node[':']) { recent = node[':']; node = node[':']; recent.param = {}; recent.param.id = part; if (!uris.length) { return node; } } else if (node['*']) { return node['*']; } else { return null; } } return null; } match_router('/user/2333', tree) // { methods: { get: [Function] }, path: '/user/:id', param: { id: 2333 } }
需要注意的是,在树节点搜索路由实现方式中,路由匹配的顺序非常重要。在 koa-router 的实现中,路由匹配是根据前缀树的搜索顺序来匹配路由的。例如,如果 url 请求的是 /user/2333 会和 /user/:userId 的路由匹配,而不会和 /user/*** 进行匹配。
总结
koa-router 作为一款灵活实用的路由中间件,在处理路由匹配的时候采用了两种不同的实现方式:通过正则表达式进行匹配和通过树节点的搜索路由。在使用上,我们可以根据项目实际情况来选择适用的实现方式,并对其细节进行优化和改进,从而使得前端的路由处理更加高效、方便和灵活。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659501fbeb4cecbf2d943ea5