装饰器包括一下几种:数据库
类中不一样声明上的装饰器将按如下规定的顺序应用:app
参数装饰器,而后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每一个实例成员。
参数装饰器,而后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每一个静态成员。
参数装饰器应用到构造函数。
类装饰器应用到类。ide
属性装饰器表达式会在运行时看成函数被调用,传入下列2个参数:函数
不常规作法,this
function isPassword(object: Object, propertyName: string) { let _propertyName = Symbol(propertyName) Object.defineProperty(object, propertyName, { set: function(val) { if (!/^[0-9a-zA-Z]{6,30}$/.test(val)) { throw new Error('密码格式错误'); } this[_propertyName] = val; return this[_propertyName]; }, get: function() { return this[_propertyName]; } }) } function isPhone(object: Object, propertyName: string) { let _propertyName = Symbol(propertyName) Object.defineProperty(object, propertyName, { set: function(val) { if (!/^\d{11}$/.test(val)) { throw new Error('电话号码格式不对'); } this[_propertyName] = val; return this[_propertyName]; }, get: function() { return this[_propertyName]; } }) } class Form { @isPhone phone: number; @isPassword passpowd: string constructor(passpowd: string, phone: number) { this.passpowd = passpowd; this.phone = phone; } } let data = new Form('acbd123', 123456789);
方法装饰器表达式会在运行时看成函数被调用,传入下列3个参数:spa
若是方法装饰器返回一个值,它会被用做方法的属性描述符。.net
示例:code
function log(target: any, propertyKey: string, descriptor: any) { var originalMethod = descriptor.value; descriptor.value = function (...args: any[]) { var result = originalMethod.apply(this, args); var r = JSON.stringify(result); console.log('返回值:' + r); return result; } return descriptor; } class Person { name: string; age: number; phone: number; constructor(name: string, age: number, phone: number) { this.name = name; this.age = age; this.phone = phone; } @log getGrowUp(year) { this.age += year; return this.age; } } const men = new Person('张三', 18, 1234567890); men.getGrowUp(5);
访问器装饰器表达式会在运行时看成函数被调用,传入下列3个参数:orm
示例:对象
class Point { private _x: number; private _y: number; constructor(x: number, y: number) { this._x = x; this._y = y; } @configurable(false) get x() { return this._x; } @configurable(false) get y() { return this._y; } } function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.configurable = value; }; } const point = new Point(50, 50); point.x = 60; console.log(point.x)
类装饰器表达式会在运行时看成函数被调用,类的构造函数做为其惟一的参数。
若是类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
注意 若是你要返回一个新的构造函数,你必须注意处理好原来的原型链。 在运行时的装饰器调用逻辑中 不会为你作这些。
示例:
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) { return class extends constructor { newProperty = "new property"; hello = "override"; } } @classDecorator class Greeter { property = "property"; hello: string; constructor(m: string) { this.hello = m; } } console.log(new Greeter("world"));
依赖注入示例
来源:https://blog.csdn.net/HaoDaWa...
//ioc容器 let classPool:Array<Function> = []; //注册该类进入容器 function Injectable(){ return (_constructor:Function) => { let paramTypes:Array<Function> = Reflect.getMetadata('design:paramtypes',_constructor) //已注册 if(classPool.indexOf(_constructor) != -1) return; for(let val of paramTypes){ if(val === _constructor) throw new Error('不能依赖本身') else if(classPool.indexOf(val) == -1) throw new Error(`${val}没有被注册`) } //注册 classPool.push(_constructor); } } //实例化工厂 function classFactory<T>(_constructor:{new(...args:Array<any>):T}):T{ let paramTypes:Array<Function> = Reflect.getMetadata('design:paramtypes',_constructor) //参数实例化 let paramInstance = paramTypes.map((val:Function) => { //依赖的类必须所有进行注册 if(classPool.indexOf(val) == -1) throw new Error(`${val}没有被注册`) //参数还有依赖 else if(val.length){ return classFactory(val as any); } //没有依赖直接建立实例 else{ return new (val as any)(); } }) return new _constructor(...paramInstance); } @Injectable() class C{ constructor(){} sayHello(){ console.log("hello") } } @Injectable() class B{ constructor(private c:C){ } sayHello(){ this.c.sayHello(); } } @Injectable() class A{ constructor(private b:B){ } say() { this.b.sayHello(); } } //产生实例 const a:A = classFactory(A); a.say()
参数装饰器表达式会在运行时看成函数被调用,传入下列3个参数:
参数装饰器一般须要配合方法装饰器和元数据
class Person { type: string; name: string; @validate login(@phone phone, @password password) { // 数据库操做... return { name: 'Ryan', phone: phone, sex: 1 } } } function validate(target, propertyKey, descriptor) { const fun = descriptor.value; descriptor.value = function() { Validator(propertyKey, target, arguments); return fun.apply(this, arguments); }; } function phone(target, propertyKey, index) { Reflect.defineMetadata(propertyKey, index, target, 'phone'); } function password(target, propertyKey, index) { Reflect.defineMetadata(propertyKey, index, target, 'password'); } function Validator(propertyKey, target, data) { let rules = [ { type: 'phone', hasError: (val) => !/^\d{11}$/.test(val), message: '手机号码的格式不对' }, { type: 'password', hasError: (val) => !/^\w{6,36}$/.test(val), message: '密码的格式不对' } ]; for (let item of rules) { let key = Reflect.getMetadata(propertyKey, target, item.type); if (data.hasOwnProperty(key)) { if (item.hasError(data[key])) { throw new BadRequestException(item.message); } } } } const p = new Person(); p.login(183206650110, 'aa1213456');