利用Decorator如何控制Koa路由详解


Posted in Javascript onJune 26, 2018

前言

在Spring中Controller长这样

@Controller
public class HelloController{
 @RequestMapping("/hello")
 String hello() {
 return "Hello World"; 
 }
}

还有Python上的Flask框架

@app.route("/hello")
def hello():
 return "Hello World"

两者都用decorator来控制路由,这样写的好处是更简洁、更优雅、更清晰。

反观Express或Koa上的路由

router.get('/hello', async ctx => {
 ctx.body = 'Hello World'
})

完全差了一个档次

JS从ES6开始就有Decorator了,只是浏览器和Node都还没有支持。需要用babel-plugin-transform-decorators-legacy转义。

Decorator基本原理

首先需要明确两个概念:

  • Decorator只能作用于类或类的方法上
  • 如果一个类和类的方法都是用了Decorator,类方法的Decorator优先于类的Decorator执行

Decorator基本原理:

@Controller
class Hello{

}

// 等同于

Controller(Hello)

Controller是个普通函数,target为修饰的类或方法

// Decorator不传参
function Controller(target) {

}

// Decorator传参
function Controller(params) {
 return function (target) {

 }
}

如果Decorator是传参的,即使params有默认值,在调用时必须带上括号,即:

@Controller()
class Hello{

}

如何在Koa中使用Decorator

我们可以对koa-router中间件进行包装

先回顾一下koa-router基本使用方法:

var Koa = require('koa');
var Router = require('koa-router');

var app = new Koa();
var router = new Router();

router.get('/', async (ctx, next) => {
 // ctx.router available
});

app
 .use(router.routes())
 .use(router.allowedMethods());

再想象一下最终目标

@Controller({prefix: '/hello'})
class HelloController{
 @Request({url: '/', method: RequestMethod.GET})
 async hello(ctx) {
 ctx.body = 'Hello World'
 }
}

类内部方法的装饰器是优先执行的,我们需要对方法重新定义

function Request({url, method}) {
 return function (target, name, descriptor) {
 let fn = descriptor.value
 descriptor.value = (router) => {
  router[method](url, async(ctx, next) => {
  await fn(ctx, next)
  })
 }
 }
}

对RequestMethod进行格式统一

const RequestMethod = {
 GET: 'get',
 POST: 'post',
 PUT: 'put',
 DELETE: 'delete'
}

Controller装饰器需将Request方法添加到Router实例并返回Router实例

import KoaRouter from 'koa-router'

function Controller({prefix}) {
 let router = new KoaRouter()
 if (prefix) {
 router.prefix(prefix)
 }
 return function (target) {
 let reqList = Object.getOwnPropertyDescriptors(target.prototype)
 for (let v in reqList) {
  // 排除类的构造方法
  if (v !== 'constructor') {
  let fn = reqList[v].value
  fn(router)
  }
 }
 return router
 }
}

至此,装饰器基本功能就完成了,基本使用方法为:

import {Controller, Request, RequestMethod} from './decorator'

@Controller({prefix: '/hello'})
export default class HelloController{
 @Request({url: '/', method: RequestMethod.GET})
 async hello(ctx) {
 ctx.body = 'Hello World'
 }
}

在App实例中同路由一样use即可。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
使用UglifyJS合并/压缩JavaScript的方法
Mar 07 Javascript
jQuery中的jQuery()方法用法分析
Dec 27 Javascript
JavaScript获取文本框内选中文本的方法
Feb 20 Javascript
HTML5 实现的一个俄罗斯方块实例代码
Sep 19 Javascript
js实现4个方向滚动的球
Mar 06 Javascript
使用mint-ui开发项目的一些心得(分享)
Sep 07 Javascript
总结js中的一些兼容性易错的问题
Dec 18 Javascript
js实现复制功能(多种方法集合)
Jan 06 Javascript
微信小程序模板(template)使用详解
Jan 31 Javascript
修改npm全局安装模式的路径方法
May 15 Javascript
详解React Native 屏幕适配(炒鸡简单的方法)
Jun 11 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
Jul 26 Javascript
vue实现点击关注后及时更新列表功能
Jun 26 #Javascript
微信小程序项目总结之点赞 删除列表 分享功能
Jun 25 #Javascript
nuxt.js 缓存实践
Jun 25 #Javascript
vue2.0使用v-for循环制作多级嵌套菜单栏
Jun 25 #Javascript
浅谈super-vuex使用体验
Jun 25 #Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
Jun 25 #Javascript
使用vue的transition完成滑动过渡的示例代码
Jun 25 #Javascript
You might like
用PHP进行MySQL删除记录操作代码
2008/06/07 PHP
php封装json通信接口详解及实例
2017/03/07 PHP
php如何比较两个浮点数是否相等详解
2019/02/12 PHP
6个DIV 135或246间隔一秒轮番显示效果
2010/07/24 Javascript
基于jQuery的让非HTML5浏览器支持placeholder属性的代码
2011/05/24 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
javascript按位非运算符的使用方法
2013/11/14 Javascript
jQuery过滤选择器详解
2015/01/13 Javascript
javascript制作照片墙及制作过程中出现的问题
2016/04/04 Javascript
js弹出窗口返回值的简单实例
2016/05/28 Javascript
微信小程序 picker 组件详解及简单实例
2017/01/10 Javascript
微信小程序实现顶部普通选项卡效果(非swiper)
2020/06/19 Javascript
react-native fetch的具体使用方法
2017/11/01 Javascript
JS实现网页抢购功能(触发,终止脚本)
2017/11/27 Javascript
vue中引用swiper轮播插件的教程详解
2018/08/16 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
基于React Native 0.52实现轮播图效果
2020/08/25 Javascript
js canvas实现二维码和图片合成的海报
2020/11/19 Javascript
轻松学习JavaScript函数中的 Rest 参数
2019/05/30 Javascript
Javascript异步编程async实现过程详解
2020/04/02 Javascript
Javascript实现简易天数计算器
2020/05/18 Javascript
JavaScript的一些小技巧分享
2021/01/06 Javascript
在Python中获取两数相除的商和余数方法
2018/11/10 Python
Python语法分析之字符串格式化
2019/06/13 Python
pytorch numpy list类型之间的相互转换实例
2019/08/18 Python
Python笔试面试题小结
2019/09/07 Python
基于Django OneToOneField和ForeignKey的区别详解
2020/03/30 Python
python 穷举指定长度的密码例子
2020/04/02 Python
日本7net购物网:书籍、漫画、杂志、DVD、游戏邮购
2017/02/17 全球购物
应征英语教师求职信
2013/11/27 职场文书
创先争优制度
2014/01/21 职场文书
临床医学生职业规划书范文
2014/10/25 职场文书
python用字节处理文件实例讲解
2021/04/13 Python
Python基础之hashlib模块详解
2021/05/06 Python
MySQL表字段时间设置默认值
2021/05/13 MySQL
浅析Python OpenCV三种滤镜效果
2022/04/11 Python