クラスに作用するデコレータはクラス デコレータであり、デコレータ入門の デコレータの最後の例は クラス デコレータです。
1. コンストラクターのクラス デコレーターを変更する必要がある
1.1. パラメータなしのデコレータ
デコレーターの紹介 で 最後に示したのは 、コンストラクターを変更するデコレーターです。
function changePrice<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
price = 666;
};
}
@changePrice
export class Grape {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
//组件中调用代码
let grape = new Grape(4);
console.log(grape);
操作結果:
1.2. パラメータ付きのデコレータ
変更に基づいて、受信パラメーターのクラス デコレーターを実装できます。
function changePrice<T extends { new(...args: any[]): {} }>(price: number) {
return (constructor: T) => {
let newConstruct = function (...args: any[]) {
let c = class extends constructor {
price = price;
};
return new c(args);
}
let func: any = function (...args: any[]) {
return newConstruct(args);
}
return func;
};
}
@changePrice(8)
export class Grape {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
@changePrice(10)
export class Banana {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
//组件中调用代码
let grape = new Grape(4);
console.log(grape);
let banana = new Banana(4);
console.log(banana);
デコレータ パラメータ と実行結果を介して値を渡すことにより、価格 フィールドを変更します。
もちろん、デコレータでクラスに新しいフィールドを追加することもできます:
function changePrice<T extends { new(...args: any[]): {} }>(price: number) {
console.log("price decorator define");
return (constructor: T) => {
console.log("price decorator");
let newConstruct = function (...args: any[]) {
let c = class extends constructor {
price = price;
};
console.log("set price");
return new c(args);
}
let func: any = function (...args: any[]) {
return newConstruct(args);
}
return func;
};
}
function color<T extends { new(...args: any[]): {} }>(color: string) {
console.log("color decorator define");
return (constructor: T) => {
console.log("color decorator");
let newConstruct = function (...args: any[]) {
let c = class extends constructor {
color = color;
};
console.log("set color");
return new c(args);
}
let func: any = function (...args: any[]) {
return newConstruct(args);
}
return func;
};
}
@color("purple")
@changePrice(8)
export class Grape {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
//组件中调用代码
let grape = new Grape(4);
console.log(grape);
let grape2 = new Grape(5);
console.log(grape2);
The above code adds a new decorator color , which modified the constructor of the target class and adds a color field. 上記のコードはまた、デコレータの順序を分析するためにいくつかのプリントを追加します。操作結果:
最後の印刷時にオブジェクトにcolorフィールドが追加されていることがわかります.追加の印刷を通じて、構築メソッド ( newConstruct )の外側の印刷が1 回だけ印刷されていることがわかります。クラスが変換され、構築メソッド内の印刷 ( newConstruct ) が新しいオブジェクトごとに実行されます。デコレータの適用順序は、外側から内側の順番に対応して、上から下への書き込み順に実行されます. 上記のコードは次のように理解できます:
@color("purple")
(
@changePrice(8)
class Grape{ ... }
)
したがって、上記の印刷順序になります。
2. コンストラクターのクラスデコレーターを変更する必要はありません
2.1. パラメータなしのデコレータ
クラスのコンストラクターを拡張および変更する必要がない場合は、より簡潔なエンコード形式を使用できます。
function enableBuy(target: Function): void {
target.prototype.buy = function (count: number) {
console.log(`need money : ${this.price * count} to buy ${count}`);
}
}
@color("purple")
@changePrice(8)
@enableBuy
export class Grape {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
//组件中调用代码
let grape: any = new Grape(4);
console.log(grape);
grape.buy(10);
コードを実行すると、次のように出力されます。
2.2. パラメータ付きのデコレータ
パラメータを渡した後にエンコード形式を追加します。
function enableBuy(coupon:number) { //coupon 打折金额
return (target: Function) => {
target.prototype.buy = function (count: number) {
console.log(`need money ${this.price * count - coupon} to buy ${count}`);
}
}
}
@color("purple")
@changePrice(8)
@enableBuy(5)
export class Grape {
price: number = 0;
constructor(price: number) {
this.price = price;
console.log(`constructor price : ${this.price}`);
}
}
//组件中调用代码
let grape: any = new Grape(4);
console.log(grape);
grape.buy(10);
コードを実行すると、次のように出力されます。
ここではクラスデコレータの使い方を紹介しますので、意見交換を歓迎します。