内容简介:从上面可以知道,如果没有koa-router,其实每个路由使用的koa注册中间件的形式来进行处理的,这样不利于松耦合和模块化,所以将所有路由的处理逻辑抽离出来组合成一个大的中间件koa-router来处理,最后将大的中间件注册到koa上,如果关于koa中间件原理还不了解,可以参考另一篇文章既然koa-router也是大的中间件,里面拥有许多小的中间件,那么里面必然也需要用到洋葱模型,洋葱模型的特点:如果对于中间件和洋葱模型有疑问的,可以参考
- koa-session:让无状态的http拥有状态,基于cookie实现的后台保存信息的session
- koa-mysql:封装了需要用到的 SQL 语句
- koa-mysql-session:当不想让session存储到内存,而想让session存储到 mysql 数据库中时使用
- koa-router:后台会接受到各种请求的url,路由会根据不同的url来使用不同的处理逻辑。
- koa-view:请求html页面时,后台会用模板引擎渲染数据到模板上,然后返回给后台
- koa-static:请求img、js、css等文件时,不需要其他逻辑,只需要读取文件
- koa-better-body:post上传文件时,解析请求体
koa系列文章:
- koa框架会用也会写—(koa的实现)
- koa框架会用也会写—(koa-router)
- koa框架会用也会写—(koa-view、koa-static)
- koa框架会用也会写—(koa-bodyparser、koa-better-body)
koa-router的使用
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());
复制代码
koa-router的奥秘
假如没有koa-router
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-router也是大的中间件,里面拥有许多小的中间件,那么里面必然也需要用到洋葱模型,洋葱模型的特点:
- middles:存放中间件的容器,用来存放注册的中间件
- get(path,fn):用来注册中间件,往middles中存放,由于是路由中间件这里多了一个参数path
- compose():用来组合中间件,让路由中间件按顺序执行
- routes():用来将koa-router中间件注册到app的中间件上,主要作用是调用路由中间件匹配请求的路径ctx.path
如果对于中间件和洋葱模型有疑问的,可以参考 koa框架会用也会写—(koa的实现)
middles:存放中间件的容器,用来存放注册的中间件
class Router {
constructor(){
this.middles=[];
}
}
module.exports = Router
复制代码
get(path,fn):用来注册中间件,往middles中存放,由于是路由中间件这里多了一个参数path
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
复制代码
compose():用来组合中间件,让路由中间件按顺序执行
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
复制代码
routes():用来将koa-router中间件注册到app的中间件上,主要作用是调用路由中间件匹配请求的路径ctx.path
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
复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于Google MVVM框架的baseMVVM框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Spring 框架是怎么出生的(二):重构提炼出框架
- Genesis框架从入门到精通(7): 框架的过滤器
- 如何打造自己的POC框架-Pocsuite3-框架篇
- 如何打造自己的PoC框架-Pocsuite3-框架篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First JavaScript Programming
Eric T. Freeman、Elisabeth Robson / O'Reilly Media / 2014-4-10 / USD 49.99
This brain-friendly guide teaches you everything from JavaScript language fundamentals to advanced topics, including objects, functions, and the browser’s document object model. You won’t just be read......一起来看看 《Head First JavaScript Programming》 这本书的介绍吧!