Decoratorの概要と動作確認をします。また、利用例として、メソッドの前後に処理を追加する方法を確認します。
目次
Decoratorとは
例えば、メソッドにDecoratorを割り当てて、そのメソッドが実行される前後に処理を付け加える(装飾する)ことができ、ログの出力などで活用されます。
Vue.jsでTypeScriptをクラスベースで利用する際、vue-class-component と vue-property-decorator を利用しますが、こちらでもDecoratorが活用されています。
Decoratorは、クラス
メソッド
アクセサ
プロパティ
パラメータ
に割り当てることが可能です。
tsconfig.jsonを修正
Decoratorを利用する場合、tsconfig.json
の下記オプションを true
にしておく必要があります。
{
"compilerOptions": {
(省略)
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */
}
}
動作確認
どのタイミングで実行されるか確認します。
// デコレータファクトリー
function f() {
console.log("f(): evaluated");
// デコレーター
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
console.log("### target ###");
console.log(target);
console.log("### propertyKey ###");
console.log(propertyKey);
console.log("### descriptor ###");
console.log(descriptor);
}
}
class TestClass {
@f()
public xxx() {
console.log("xxx method processing");
}
}
console.log("create object");
const testClass = new TestClass();
console.log("before xxx");
testClass.xxx();
f(): evaluated
f(): called
### target ###
TestClass { xxx: [Function] }
### propertyKey ###
xxx
### descriptor ###
{ value: [Function],
writable: true,
enumerable: true,
configurable: true }
create object
before xxx
xxx method processing
メソッドの前後に処理を追加
元のメソッドを1度退避させて、前処理、後処理を装飾します。
function f() {
console.log("f(): evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
console.log("### target ###");
console.log(target);
console.log("### propertyKey ###");
console.log(propertyKey);
console.log("### descriptor ###");
console.log(descriptor);
const originalMethod = descriptor.value; // 元のメソッドを退避
descriptor.value = function () {
console.log("Decorate pre processing");
const ret = originalMethod.apply(this, arguments); // 元のメソッドを実行
console.log("Decorate post processing");
return ret;
}
}
}
class TestClass {
@f()
public xxx() {
console.log("xxx method processing");
}
}
console.log("create object");
const testClass = new TestClass();
console.log("before xxx");
testClass.xxx();
f(): evaluated
f(): called
### target ###
TestClass { xxx: [Function] }
### propertyKey ###
xxx
### descriptor ###
{ value: [Function],
writable: true,
enumerable: true,
configurable: true }
create object
before xxx
Decorate pre processing
xxx method processing
Decorate post processing