利用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 相关文章推荐
JavaScript作用域链使用介绍
Aug 29 Javascript
JS两种定义方式的区别、内部原理
Nov 21 Javascript
常用的JavaScript模板引擎介绍
Feb 28 Javascript
jQuery插件zoom实现图片全屏放大弹出层特效
Apr 15 Javascript
jQuery横向擦除焦点图特效代码分享
Sep 06 Javascript
详解JavaScript的Date对象(制作简易钟表)
Apr 07 Javascript
AngularJS  $modal弹出框实例代码
Aug 24 Javascript
js实现表单及时验证功能 用户信息立即验证
Sep 13 Javascript
微信小程序本作用域下调用全局JS详解及实例
Feb 22 Javascript
HTML5实现微信拍摄上传照片功能
Apr 21 Javascript
20个最常见的jQuery面试问题及答案
May 23 jQuery
使用Javascript简单计算器
Nov 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
附件名前加网站名
2008/03/23 PHP
js+数组实现网页上显示时间/星期几的实用方法
2013/01/18 Javascript
jQuery:delegate中select()不起作用的解决方法(实例讲解)
2014/01/26 Javascript
jquery动态改变form属性提交表单
2014/06/03 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
js格式化时间小结
2014/11/03 Javascript
ECMAScript6块级作用域及新变量声明(let)
2015/06/12 Javascript
$.extend 的一个小问题
2015/06/18 Javascript
使用vue构建移动应用实战代码
2017/08/02 Javascript
动态内存分配导致影响Javascript性能的问题
2018/12/18 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
laravel-admin 与 vue 结合使用实例代码详解
2019/06/04 Javascript
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
python爬虫获取京东手机图片的图文教程
2017/12/29 Python
python邮件发送smtplib使用详解
2020/06/16 Python
Python实现迭代时使用索引的方法示例
2018/06/05 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
对Django项目中的ORM映射与模糊查询的使用详解
2019/07/18 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
2020/02/28 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
2020/06/23 Python
Python sublime安装及配置过程详解
2020/06/29 Python
python中四舍五入的正确打开方式
2021/01/18 Python
CSS3新增布局之: flex详解
2020/06/18 HTML / CSS
宝拉珍选美国官网:Paula’s Choice美国
2018/01/07 全球购物
苏格兰销售女装、男装和童装的连锁店:M&Co
2018/03/16 全球购物
JPA面试常见问题
2016/11/14 面试题
师范应届生教师求职信
2013/11/05 职场文书
财务工作个人求职的自我评价
2013/12/19 职场文书
公司离职证明范本(5篇)
2014/09/17 职场文书
《爱的教育》读书心得
2014/11/08 职场文书
2016预备党员培训心得体会
2016/01/08 职场文书
python requests模块的使用示例
2021/04/07 Python
QT与javascript交互数据的实现
2021/05/26 Javascript
MySQL GRANT用户授权的实现
2021/06/18 MySQL
Mysql如何实现不存在则插入,存在则更新
2022/03/25 MySQL
Win11 vmware不兼容怎么办?Win11与VMware虚拟机不兼容的解决方法
2023/01/09 数码科技