裝飾器包括一下幾種:數據庫
類中不一樣聲明上的裝飾器將按如下規定的順序應用: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');