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

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

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

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

查看所有标签

猜你喜欢:

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

Head First JavaScript Programming

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》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码