利用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 相关文章推荐
不用ajax实现点击文字即可编辑的方法
Dec 16 Javascript
JavaScript实现表格排序方法
Jun 14 Javascript
动态的创建一个元素createElement及删除一个元素
Jan 24 Javascript
Javascript前端UI框架Kit使用指南之Kitjs简介
Nov 28 Javascript
完美实现bootstrap分页查询
Dec 09 Javascript
Javascript中的几种继承方式对比分析
Mar 22 Javascript
jquery获取复选框checkbox的值的简单实现方法
May 26 Javascript
jQuery 3.0中存在问题及解决办法
Jul 15 Javascript
AngularJS ngModel实现指令与输入直接的数据通信
Sep 21 Javascript
详解ES6中的let命令
Apr 05 Javascript
Vue.Draggable拖拽功能的配置使用方法
Jul 29 Javascript
基于JS实现web端录音与播放功能
Apr 17 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 写文本日志实现代码
2010/05/18 PHP
PHP把JPEG图片转换成Progressive JPEG的方法
2014/06/30 PHP
thinkphp的dump函数无输出实例代码
2016/11/15 PHP
php+js实现的拖动滑块验证码验证表单操作示例【附源码下载】
2020/05/27 PHP
javascript算法学习(直接插入排序)
2011/04/12 Javascript
Jquery实现带动画效果的经典二级导航菜单
2013/03/22 Javascript
js中的push和join方法使用介绍
2013/10/08 Javascript
JavaScript中使用Substring删除字符串最后一个字符
2013/11/03 Javascript
js禁止页面使用右键(简单示例代码)
2013/11/13 Javascript
使用Jquery获取带特殊符号的ID 标签的方法
2014/04/30 Javascript
JavaScript父子窗体间的调用方法
2015/03/31 Javascript
jQuery+HTML5实现图片上传前预览效果
2015/08/20 Javascript
JS快速实现移动端拼图游戏
2016/09/05 Javascript
vue2.0开发实践总结之疑难篇
2016/12/07 Javascript
很棒的一组js图片轮播特效
2017/01/12 Javascript
javascript自执行函数
2017/02/10 Javascript
angular2 ng2 @input和@output理解及示例
2017/10/10 Javascript
VUE中V-IF条件判断改变元素的样式操作
2020/08/09 Javascript
python三元运算符实现方法
2013/12/17 Python
python 禁止函数修改列表的实现方法
2017/08/03 Python
推荐10款最受Python开发者欢迎的Python IDE
2018/09/16 Python
Python设计模式之策略模式实例详解
2019/01/21 Python
Python 用三行代码提取PDF表格数据
2019/10/13 Python
python中@property和property函数常见使用方法示例
2019/10/21 Python
python错误调试及单元文档测试过程解析
2019/12/19 Python
详解KMP算法以及python如何实现
2020/09/18 Python
介绍一下Java的事务处理
2012/12/07 面试题
vue实现倒计时功能
2021/03/24 Vue.js
卫校护理专业毕业生求职信
2013/11/26 职场文书
学生操行评语大全
2014/04/24 职场文书
安全资料员岗位职责范本
2014/06/28 职场文书
学校运动会广播稿范文
2014/10/02 职场文书
会计求职自荐信范文
2015/03/04 职场文书
入党转正申请报告
2015/05/15 职场文书
大学生暑期实践报告
2015/07/13 职场文书
七年级作文之秋游
2019/10/21 职场文书