我有两个装饰器,当我将它们附加到一个属性时,只有第一个定义了执行它的setter/getter属性。内部函数本身运行Init Decorator 1和Init Decorator 2。是什么导致第二个装饰器不执行setter/getter?
下面是我如何定义我的两个装饰师的方法:
export function Decorator1(): any {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor = descriptor || {};
console.log('Init Decorator 1');
descriptor.get = function (this: any) { console.log('Get Decorator 1'); }
descriptor.set = function (this: any) { console.log('Set Decorator 1'); }
return descriptor;
}
}
export function Decorator2(): any {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor = descriptor || {};
console.log('Init Decorator 2');
descriptor.get = function (this: any) { console.log('Get Decorator 2'); }
descriptor.set = function (this: any) { console.log('Set Decorator 2'); }
return descriptor;
}
}然后,我将按以下方式使用这些装饰师:
export class Test {
@Decorator1()
@Decorator2()
code = '';
constructor() {
setTimeout(() => this.code = '123', 2000);
}
}
new Test();[LOG]: "Init Decorator 2"
[LOG]: "Init Decorator 1"
[LOG]: "Set Decorator 1"
[LOG]: "Set Decorator 1" 发布于 2022-07-03 18:00:29
根据访问器装饰器的TypeScript文档,当这样的装饰器返回一个值时,它将替换相关属性的属性描述符。当你组合装饰师的时候,它们是自下而上的.
因此,在示例代码中
@Decorator1()
@Decorator2()
code = '';您首先使用最初未定义的属性描述符,并将其替换为Decorator2描述符。然后,您将获取该Decorator2描述符,并通过重新分配其get和set属性来修改它。重新分配属性不以任何方式保留先前的属性。包含set()的"Set Decorator 2"方法已被丢弃。糟了。
这取决于您如何编写属性描述符。想必您应该分析传递给您的装饰器的descriptor值,并保留它的get和set属性,但是您认为合适。例如:
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor = descriptor || {};
const prevGet = descriptor.get;
const prevSet = descriptor.set;
console.log('Init Decorator N');
descriptor.get = function (this: any) {
console.log('Get Decorator N');
if (prevGet) prevGet.call(this);
}
descriptor.set = function (this: any, v) {
console.log('Set Decorator N');
if (prevSet) prevSet.call(this, v);
}
return descriptor;
}在这里,我们保存get和set的前两个值,如果定义了它们,则在新的get和set方法中调用它们。请注意,我并不担心前面的方法会返回什么,特别是对于get,您可能会担心。这取决于您运行它们的顺序;这里,我在现有的方法逻辑之前运行新的方法逻辑。这里最重要的一点是,如果以某种方式保存之前的描述符状态,则需要显式地关注它。
使用这种方法可以得到以下结果:
[LOG]: "Init Decorator 2" // Decorator2 runs first
[LOG]: "Init Decorator 1" // Then Decorator1,
[LOG]: "Set Decorator 1" // Decorator1's logic runs first
[LOG]: "Set Decorator 2" // Then Decorator2's logic is run inside of Decorator1's set
[LOG]: "Set Decorator 1" // ditto
[LOG]: "Set Decorator 2" // dittohttps://stackoverflow.com/questions/72848113
复制相似问题