パラメータ デコレータは、パラメータ宣言の前に宣言されます。パラメーター デコレーターは、クラス コンストラクターまたはメソッドによって宣言された関数に適用されます。
パラメータ デコレータは、次の 3 つのパラメータを受け入れます。
target: Object - 装飾されるクラス
propertyKey: string | symbol - メソッド名
parameterIndex: number - メソッド内のパラメーターのインデックス値
パラメーター デコレーターは通常、メソッド デコレーターと組み合わせて使用され、いくつかの特別な機能を実現します。
1. パラメータなしのパラメータデコレータ
次のコードは、パラメーター デコレーターを使用して、メソッドの入力パラメーターに対して null 以外のチェックを実行する方法を示しています。
export class User {
@validate
say(@required sth: string) {
console.log(`user say: ${sth}`);
}
}
//组件中调用
let user = new User();
user.say("");
user.say("hi");
実行中の印刷物:
プログラムは、必要なデコレーター で追加されたパラメーターの非 null 値をチェックし、受信パラメーターが空の文字列の場合にエラー メッセージを出力することがわかります。ここでは、検証機能を実現するために、検証ツール クラスを追加します。
export class Validator {
private static requiredMap: Map<any, Map<string, any>> = new Map();
static registerRequired(target: any, methodName: string, paramIndex: number) {
let targetMap = this.requiredMap.get(target);
if (!targetMap) {
targetMap = new Map();
this.requiredMap.set(target, targetMap);
}
let methodMap = targetMap.get(methodName);
if (!methodMap) {
methodMap = new Map();
targetMap.set(methodName, methodMap);
}
methodMap.set(paramIndex, true);
}
static validateRequired(target: any, methodName: string, paramValues: any[]): boolean {
let targetMap = this.requiredMap.get(target);
if (!targetMap) return true;
let methodMap = targetMap.get(methodName);
if (!methodMap) return true;
for (const [index, paramValue] of paramValues.entries()) {
let required = methodMap.get(index);
if (!!required) {
if (typeof paramValue === 'undefined' || paramValue === null || paramValue === "") {
console.error(`param at index ${index} for method ${methodName} must have non-null value.`);
return false;
}
}
}
return true;
}
}
このうち、registerRequired メソッドは検証が必要なメソッドパラメーター情報の登録に使用され、validateRequired メソッドはメソッドパラメーターの検証に使用されます。
必要なパラメータデコレータのコードに検証情報を登録します。
function required(target: any, propertyKey: string, parameterIndex: number) {
Validator.registerRequired(target, propertyKey, parameterIndex);
}
検証メソッド デコレーターのコード で検証メソッドを呼び出します。
function validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
if (!Validator.validateRequired(target, propertyKey, args)) {
return;
}
return originalMethod.apply(this, args);
}
}
2. パラメータ付きのパラメータ デコレータ
もちろん、パラメータ デコレータはパラメータを渡すこともできます。上記のコードは、メソッド パラメータの正規表現の検証を満たすように変更されています。
変更された User クラス:
export class User {
name: string = "";
mail: string = "";
@validate
say(@required sth: string) {
console.log(`user say: ${sth}`);
}
@validate
setInfo(@reg('^[A-Za-z0-9]+$') name: string, @reg('^[A-Za-z0-9]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$') mail: string) {
this.name = name;
this.mail = mail;
console.log(`name: ${this.name}, mail: ${this.mail}`);
}
}
setInfoメソッドは、名前を入力できる英字と数字のみに制限し、メールをメールボックスの形式に合わせて制限します。
検証ツール クラスを変更し、正規表現の登録および検証メソッドを追加します。
private static regMap: Map<any, Map<string, any>> = new Map();
static registerReg(target: any, methodName: string, paramIndex: number, pattern: string) {
let targetMap = this.regMap.get(target);
if (!targetMap) {
targetMap = new Map();
this.regMap.set(target, targetMap);
}
let methodMap = targetMap.get(methodName);
if (!methodMap) {
methodMap = new Map();
targetMap.set(methodName, methodMap);
}
methodMap.set(paramIndex, pattern);
}
static validateReg(target: any, methodName: string, paramValues: any[]): boolean {
let targetMap = this.regMap.get(target);
if (!targetMap) return true;
let methodMap = targetMap.get(methodName);
if (!methodMap) return true;
for (const [index, paramValue] of paramValues.entries()) {
let pattern = methodMap.get(index);
if (!!pattern) {
let pass = new RegExp(pattern).test(paramValue);
if (!pass) {
console.error(`param at index ${index} for method ${methodName} does not match regular expression.\nwanted: ${pattern}\npassed value: ${paramValue}`);
return false;
}
}
}
return true;
}
Regパラメータ デコレータ コード:
function reg(pattern: string) {
return function (target: any, propertyKey: string, parameterIndex: number) {
Validator.registerReg(target, propertyKey, parameterIndex, pattern);
}
}
validate メソッド デコレーターのコードを変更して、正規表現の検証を追加します。
function validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
if (!Validator.validateRequired(target, propertyKey, args)) {
return;
}
if (!Validator.validateReg(target, propertyKey, args)) {
return;
}
return originalMethod.apply(this, args);
}
}
コンポーネント内の呼び出しコード:
let user = new User();
user.say("");
user.say("hi");
user.setInfo("..", "dd");
user.setInfo("abc1", "dd");
user.setInfo("1", "[email protected]");
実行中の印刷物:
メソッド デコレータと組み合わせて正規表現を指定するパラメータ デコレータは、メソッドのパラメータの正規表現一致をチェックし、一致規則を満たさないパラメータはメソッドを呼び出さないことがわかります。
3. 複数のパラメーター デコレーターによるパラメーターの装飾
もちろん、同じパラメータは複数のデコレータの追加をサポートします. say メソッドを変更して、 requiredデコレータと regデコレータを同時にパラメータに追加します . regデコレータは、shit を含む文字列の受け渡しを制限します.これは、禁止された文字列に相当します. コードを変更します次のように:
@validate
say(@required @reg('^(?!.*?shit).*$') sth: string) {
console.log(`user say: ${sth}`);
}
コンポーネント内の呼び出しコード:
let user = new User();
user.say("");
user.say("shit");
user.say("hi");
実行中の印刷物:
目的の効果が得られていることがわかります。
上記のプログラムの動作を分析すると、パラメーターデコレーターのコードはコンパイル時に実行され、メソッドデコレーターのコードはメソッドが呼び出されるたびに実行されることがわかります。
ここではパラメータ デコレータの使用法を紹介します。意見交換を歓迎します。