利用Decorator如何控制Koa路由詳解
前言
在Spring中Controller長(zhǎng)這樣
@Controller
public class HelloController{
@RequestMapping("/hello")
String hello() {
return "Hello World";
}
}
還有Python上的Flask框架
@app.route("/hello")
def hello():
return "Hello World"
兩者都用decorator來(lái)控制路由,這樣寫的好處是更簡(jiǎn)潔、更優(yōu)雅、更清晰。
反觀Express或Koa上的路由
router.get('/hello', async ctx => {
ctx.body = 'Hello World'
})
完全差了一個(gè)檔次
JS從ES6開始就有Decorator了,只是瀏覽器和Node都還沒有支持。需要用babel-plugin-transform-decorators-legacy轉(zhuǎn)義。
Decorator基本原理
首先需要明確兩個(gè)概念:
- Decorator只能作用于類或類的方法上
- 如果一個(gè)類和類的方法都是用了Decorator,類方法的Decorator優(yōu)先于類的Decorator執(zhí)行
Decorator基本原理:
@Controller
class Hello{
}
// 等同于
Controller(Hello)
Controller是個(gè)普通函數(shù),target為修飾的類或方法
// Decorator不傳參
function Controller(target) {
}
// Decorator傳參
function Controller(params) {
return function (target) {
}
}
如果Decorator是傳參的,即使params有默認(rèn)值,在調(diào)用時(shí)必須帶上括號(hào),即:
@Controller()
class Hello{
}
如何在Koa中使用Decorator
我們可以對(duì)koa-router中間件進(jìn)行包裝
先回顧一下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());
再想象一下最終目標(biāo)
@Controller({prefix: '/hello'})
class HelloController{
@Request({url: '/', method: RequestMethod.GET})
async hello(ctx) {
ctx.body = 'Hello World'
}
}
類內(nèi)部方法的裝飾器是優(yōu)先執(zhí)行的,我們需要對(duì)方法重新定義
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)
})
}
}
}
對(duì)RequestMethod進(jìn)行格式統(tǒng)一
const RequestMethod = {
GET: 'get',
POST: 'post',
PUT: 'put',
DELETE: 'delete'
}
Controller裝飾器需將Request方法添加到Router實(shí)例并返回Router實(shí)例
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實(shí)例中同路由一樣use即可。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
利用node.js啟動(dòng)本地服務(wù)器的操作指南(超詳細(xì))
這篇文章主要介紹了利用node.js啟動(dòng)本地服務(wù)器的操作指南(超詳細(xì)),有很多小伙伴制作網(wǎng)站或者小程序時(shí),需要通過服務(wù)器來(lái)把前端和后端連接起來(lái),那么我們今天學(xué)習(xí)啟動(dòng)node.js服務(wù)器,文中有詳細(xì)的代碼示例和圖文供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2024-05-05
Node.js重新刷新session過期時(shí)間的方法
在Node.js中,我們通常使用express-session這個(gè)包來(lái)使用和管理session,保存服務(wù)端和客戶端瀏覽器之間的會(huì)話狀態(tài)。那如何才能實(shí)現(xiàn)當(dāng)用戶刷新當(dāng)前頁(yè)面或者點(diǎn)擊頁(yè)面上的按鈕時(shí)重新刷新session的過期時(shí)間呢,接下來(lái)通過本文一起學(xué)習(xí)吧2016-02-02
nodeJS代碼實(shí)現(xiàn)計(jì)算交社保是否合適
本文通過nodejs的一個(gè)具體示例來(lái)對(duì)比分析現(xiàn)階段我們交社保合不合適,主要是對(duì)nodejs的一個(gè)小的應(yīng)用,當(dāng)然大家也可以改成其他語(yǔ)言的,程序猿們,來(lái)算算吧。2015-03-03
關(guān)于npm install過程失敗的幾種處理方式
這篇文章主要介紹了關(guān)于npm install過程失敗的幾種處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

