/**
* typescript
* 簡單實現(xiàn)在express中使用路由裝飾器,
* @author: dottie
* @created at: 2019-01-21 13:24:56
*/
import "reflect-metadata";
const PATH_METADATA = Symbol();
const METHOD_METADATA = Symbol();
// 這里的target是 class Home
function Controller(path: string): ClassDecorator {
return (target: any) => {
Reflect.defineMetadata(PATH_METADATA, path, target);
}
}
// 這里的target是 class Home 的 prototype 等價于 Object.getPrototypeOf(new Home()); 也即為 (new Home()).__proto__
function createMethod(method: string) {
return (path: string): MethodDecorator => {
return (target: any, key: string | symbol, descriptor: any) => {
Reflect.defineMetadata(PATH_METADATA, path, target, descriptor.value);
Reflect.defineMetadata(METHOD_METADATA, method, target, descriptor.value);
}
}
}
const Get = createMethod('get');
const Post = createMethod('post');
@Controller('/home')
class Home {
@Get("/data")
getData() {
return "get data method!";
}
@Get('/book')
getBook() {
return "return book method!";
}
@Post('/register')
register() {
return 'register success!';
}
}
function isFunction(arg: any): boolean {
return typeof arg === 'function';
}
function isConstructor(arg: string) {
return arg === 'constructor';
}
// 定義RouteInfo類型;
interface RouteInfo {
rootPath: string,
pathInfo: {
path: string,
method: string,
fn: Function,
methodName: string
}[]
}
const mapRoute = (instance: Object): RouteInfo => {
const prototype = Object.getPrototypeOf(instance);
const rootPath = Reflect.getMetadata(PATH_METADATA, prototype.constructor);
const properties = Object.getOwnPropertyNames(prototype).filter(item => !isConstructor(item) && isFunction(prototype[item]));
let pathInfo = properties.map(item => {
const path = Reflect.getMetadata(PATH_METADATA, prototype, prototype[item]);
const method = Reflect.getMetadata(METHOD_METADATA, prototype, prototype[item]);
return { path, method, fn: prototype[item], methodName: item };
});
return {
rootPath,
pathInfo
};
}
let r = mapRoute(new Home())
console.log(r);
/**
*
{
rootPath: '/home',
pathInfo:
[ { path: '/data',
method: 'get',
fn: [Function],
methodName: 'getData' },
{ path: '/book',
method: 'get',
fn: [Function],
methodName: 'getBook' },
{ path: '/register',
method: 'post',
fn: [Function],
methodName: 'register' }
]
}
*/
// call method
let getData = r.pathInfo[0].fn.call(null);
console.log(getData); // get data method!
let register = r.pathInfo[2].fn.call(null);
console.log(register); // register success!
express中簡單裝飾器實現(xiàn)(typescript)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
推薦閱讀更多精彩內(nèi)容
- 前言 本文主要講解如何使用TypeScript裝飾器定義Express路由。文中出現(xiàn)的代碼經(jīng)過簡化不能直接運行,完...