我试图在Angular 7中创建一个属性装饰器,以在set变量上初始化一个类
export class NewDataClass() {
public readonly status = { loaded: false }
public greet() {
return 'hello';
}
}
并构建一个装饰器,该装饰器返回带有某些参数的新类
export function NStatus() {
return function(target: Object, key: string | symbol): any {
return new NewDataClass();
};
}
@Component({
selector: 'app-new',
templateUrl: './new.component.n.html',
styleUrls: ['./new.component.n.scss']
})
export class NewComponent implements OnInit, OnDestroy {
@NStatus() public status: NewDataClass;
}
初始化组件时,status
的值应为new NewDataClass
。帮助
答案 0 :(得分:3)
您不能直接通过装饰器执行此操作。装饰器是在创建类(而不是实例化)时调用的,因此我们所要做的就是更改类本身以适应我们的需求。
一种选择是将字段转换为属性,并在getter上实例化值:
function NStatus() {
return function (target: Object, key: string, desc?: PropertyDescriptor): PropertyDescriptor {
return {
get: function (this: Record<string, NewDataClass>) {
return this["_" + key] || (this["_" + key] = new NewDataClass())
},
set: function (this: Record<string, NewDataClass>, value: NewDataClass) {
this["_" + key] = value
}
}
}
}
class NewComponent {
@NStatus() public status: NewDataClass;
}
console.log(new NewComponent().status);
另一种选择,因为我们正在谈论角度分量,所以我们可以从装饰器覆盖ngOnInit
并在那里进行初始化:
function NStatus() {
return function <K extends PropertyKey>(target: { ngOnInit?: () => void }, key: K): void {
const originalNgOnInit = target.ngOnInit;
target.ngOnInit = function (this: Record<K, NewDataClass>) {
// Init the field
this[key] = new NewDataClass;
// Call original ngOnInit if any
if(originalNgOnInit) originalNgOnInit.call(this);
}
}
}
class NewComponent {
@NStatus() public status: NewDataClass;
ngOnInit () {}
}
const c = new NewComponent()
c.ngOnInit();
console.log(c.status);
不幸的是,不可能从属性描述符中拦截类构造函数。