/**
* typescript
* 简单实现在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中简单装饰器实现(typescript)
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 前言 本文主要讲解如何使用TypeScript装饰器定义Express路由。文中出现的代码经过简化不能直接运行,完...