var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
router.get('/home',(ctx,next)=>{
ctx.body = 'home'
next();
});
router.get('/user', (ctx, next) => {
ctx.body = 'user';
next();
});
app.use(router.routes()).use(router.allowedMethods());
复制代码
var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
//将路由的处理交给中间件
app.use((ctx, next) => {
if (ctx.path === '/' && ctx.method === 'GET') {
ctx.body = '首页'
} else {
next();
}
})
app.use((ctx, next) => {
if (ctx.path === '/user' && ctx.method === 'GET') {
ctx.body = '用户'
} else {
next();
}
});
复制代码
从上面可以知道,如果没有koa-router,其实每个路由使用的koa注册中间件的形式来进行处理的,这样不利于松耦合和模块化,所以将所有路由的处理逻辑抽离出来组合成一个大的中间件koa-router来处理,最后将大的中间件注册到koa上,如果关于koa中间件原理还不了解,可以参考另一篇文章koa框架会用也会写—(koa的实现)
既然koa-router也是大的中间件,里面拥有许多小的中间件,那么里面必然也需要用到洋葱模型,洋葱模型的特点:
如果对于中间件和洋葱模型有疑问的,可以参考koa框架会用也会写—(koa的实现)
class Router {
constructor(){
this.middles=[];
}
}
module.exports = Router
复制代码
class Router {
constructor(){
this.middles=[];
}
get(path,fn){//set,post等同理
let layer = {
path,
fn,
method
}
//处理类似/article/:id的路由
if(path.includes(':')){
let params = [];
let reg = path.replace(/:([^\/]*)/g,function () {
params.push(arguments[1]); //params = [id]
return '([^\/]*)' //返会字符串/article/([^\/]*)
});
//将返回的字符串变成正则,后面解析路由是会用到
layer.reg = new RegExp(reg);//返回/\/article\/([^\/]*)/
layer.params = params;
}
this.middles.push(layer);
}
}
module.exports = Router
复制代码
class Router {
constructor(){
this.middles=[];
}
get(path,fn){//set,post等同理
let layer = {
path,
fn,
method
}
//处理类似/article/:id的路由
if(path.includes(':')){
let params = [];
let reg = path.replace(/:([^\/]*)/g,function () {
params.push(arguments[1]); //params = [id]
return '([^\/]*)' //返会字符串/article/([^\/]*)
});
//将返回的字符串变成正则,后面解析路由是会用到
layer.reg = new RegExp(reg);//返回/\/article\/([^\/]*)/
layer.params = params;
}
this.middles.push(layer);
}
compose(lasts,next,ctx){//lasts为匹配的路由集合
dispatch(index){
if(index === lasts.length) return next();
let route = lasts[index];
//将路径参数都取出来exp:id的值
let params = route.params;
let [, ...args] = pathname.match(route.reg);
ctx.request.params = params.reduce((memo,key,index)=>(memo[key] = args[index], memo), {});
//执行路由逻辑,next赋值为下一个路由逻辑
route.fn(ctx,()=>{
dispatch(index+1);
})
}
dispatch(0)
}
}
module.exports = Router
复制代码
class Router {
constructor(){
this.middles=[];
}
get(path,fn){//set,post等同理
let layer = {
path,
fn,
method
}
//处理类似/article/:id的路由
if(path.includes(':')){
let params = [];
let reg = path.replace(/:([^\/]*)/g,function () {
params.push(arguments[1]); //params = [id]
return '([^\/]*)' //返会字符串/article/([^\/]*)
});
//将返回的字符串变成正则,后面解析路由是会用到
layer.reg = new RegExp(reg);//返回/\/article\/([^\/]*)/
layer.params = params;
}
this.middles.push(layer);
}
compose(lasts,next,ctx){//lasts为匹配的路由集合
dispatch(index){
if(index === lasts.length) return next();
let route = lasts[index];
route.fn(ctx,()=>{
dispatch(index+1);
})
}
dispatch(0)
}
routes() {
// ctx上下文next指的是koa中的next方法
return async (ctx, next) => {
let pathname = ctx.path; //请求的路径
let lasts = this.middles.filter(item => {
if (route.reg) { // 说明当前路由是一个路径参数
if (method === route.method && route.reg.test(pathname)) {
return true //路径参数匹配到了,添加进路由组
}
}
if ((method === route.method || route.method === 'all') && (route.p === pathname || route.p === '*')) {
return true //路径是'/'或者'all',添加进路由组
}
return false;
});
this.compose(lasts, next, ctx);
}
}
}
module.exports = Router
复制代码
上面的router是简化版的koa-router,它只实现了koa-router中的一级路由,但是却是能说明koa-router的主要思想,koa-router中添加了use来注册二级路由,同时添加了很多包括重定向等其他逻辑处理
koa-router中间件的原理基本就介绍完了,后面一起学习kao的其他中间件:
作者:梦想攻城狮
链接:https://juejin.im/post/5bad90b8f265da0aac6fe9ee
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。