持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
王志远,微医前端技术部
先看应用
应用规则:对于路由传参,通常有两种写法
- 请求时以
?key=val
的形式,获取时req.query
- 定义时以
/:key1/:key2
的形式,请求时以/val1/val2
的形式,获取时req.params
app.get('/wzy1/:id/:name',function (req,res){
console.log(req.params);
res.end(JSON.stringify(req.params))
})
app.get('/wzy2',function (req,res){
console.log(req.query);
res.end(JSON.stringify(req.query))
})
实现思路
第一种,其实只要进行下以?
截取,然后进行split
,组装成为对象赋值在req.query
属性上即可
重点实现第二种,关键是 1. 如何获取请求路径上的参数 2. 如何根据这种规定进行路由的匹配
很自然的,我们可以想到用正则,正则中的分组模式可以让我们获取到符合条件情况下的某部分的值
具体实现
首先看个例子
let configUrl = '/wzy/:id/:name';
let keys = [];
configUrl = configUrl.replace(/:([^\/]+)/g,function (){
keys.push(arguments[1]);
return '([^\/]+)'
})
let reg = new RegExp(configUrl);
let requestUrl = '/wzy/1/2';
let [,...args] = requestUrl.match(reg);
let params = {};
keys.forEach((key ,i) => {
params[key] = args[i]
})
console.log(params);// {id: 1, name: 2}
其实这种功能是有第三方包的,path-to-regexp
,改写后如下
const {pathToRegexp} = require('path-to-regexp')
console.log(pathToRegexp);
let configUrl = '/wzy/:id/:name';
let keys = [];
regExp = pathToRegexp(configUrl,keys);
console.log(regExp, keys);
核心功能实现了,那我们开始接入express
中,主要是改写路由匹配逻辑
接入正则
Layer.js
const pathToRegExp = require('path-to-regexp')
function Layer(path, handler) {
this.path = path;
this.regExp = pathToRegExp(this.path, this.keys = []);
console.log(this.regExp, this.keys)
this.handler = handler;
}
改写 macth
Layer.js
Layer.prototype.match = function(pathname) {
// pathname = /user /user
if (this.path == pathname) {
return true;
}
// 中间件只有开头就可以
let r = pathname.match(this.regExp);
if(r){
let [, ...matches] = r; // 正则匹配的结果 1 个是匹配到的整个结果 2 第一个分组 3 第二个分组
this.params = {};
this.keys.forEach((item, index) => {
this.params[item.name] = matches[index]
});
return true;
}
if (!this.route) {
if (this.path == '/') { // / 可以匹配任何路径
return true;
}
// /user/add
return pathname.startsWith(this.path + '/')
}
// todo ...
return false;
}