koa框架会用也会写—(koa-router)

栏目: Node.js · 发布时间: 6年前

内容简介:从上面可以知道,如果没有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-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
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

成为乔布斯

成为乔布斯

[美] 布伦特·施兰德、[美] 里克·特策利 / 陶亮 / 中信出版集团 / 2016-10 / 69.00元

本书描绘了一位多姿多彩的人物将与生俱来的激情与成熟的管理方式相结合,打造出史上最有价值、最受消费者追捧的公司,这本书将彻底改变我们看待乔布斯的方式。 本书推翻了关于史蒂夫·乔布斯的传说和陈词滥调,比如他是天才和混蛋的结合体,暴躁易怒、自私自利,怠慢朋友与家人。本书揭示了这位苹果联合创始人和CEO的家庭生活与职业生涯,并回答了一个关键问题:为什么如此轻狂傲慢、以至于被赶出苹果的年轻人能成为史上......一起来看看 《成为乔布斯》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具