本文首發(fā)于:用Decorator控制Koa路由
Koa
在Spring中Controller長這樣
@Controller
public class HelloController{
@RequestMapping("/hello")
String hello() {
return "Hello World";
}
}
還有Python上的Flask框架
@app.route("/hello")
def hello():
return "Hello World"
兩者都用decorator來控制路由霉旗,這樣寫的好處是更簡潔、更優(yōu)雅昌执、更清晰。
反觀Express或Koa上的路由
router.get('/hello', async ctx => {
ctx.body = 'Hello World'
})
完全差了一個檔次
JS從ES6開始就有Decorator
了捺典,只是瀏覽器和Node都還沒有支持恐锣。需要用babel-plugin-transform-decorators-legacy
轉(zhuǎn)義。
Decorator基本原理
首先需要明確兩個概念:
- Decorator只能作用于類或類的方法上
- 如果一個類和類的方法都是用了Decorator纵刘,類方法的Decorator優(yōu)先于類的Decorator執(zhí)行
Decorator基本原理:
@Controller
class Hello{
}
// 等同于
Controller(Hello)
Controller是個普通函數(shù),target
為修飾的類或方法
// Decorator不傳參
function Controller(target) {
}
// Decorator傳參
function Controller(params) {
return function (target) {
}
}
如果Decorator是傳參的崔兴,即使params有默認值彰导,在調(diào)用時必須帶上括號,即:
@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'
}
}
類內(nèi)部方法的裝飾器是優(yōu)先執(zhí)行的敲茄,我們需要對方法重新定義
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進行格式統(tǒng)一
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) {
// 排除類的構(gòu)造方法
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即可堰燎。
原文地址:用Decorator控制Koa路由
我的博客:Bougie的博客