装饰器包括一下几种:
- 属性装饰器
- 方法装饰器
- 访问器装饰器
- 类装饰器
- 参数装饰器
类中不同声明上的装饰器将按以下规定的顺序应用:
参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。
参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员。
参数装饰器应用到构造函数。
类装饰器应用到类。
属性装饰器
属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
不常规做法,
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个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
如果方法装饰器返回一个值,它会被用作方法的属性描述符。
示例:
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个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
示例:
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');
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。