使用属性装饰器来启动一个类

Posted

技术标签:

【中文标题】使用属性装饰器来启动一个类【英文标题】:Use a property decorator to initiate a class 【发布时间】:2019-10-08 12:43:48 【问题描述】:

我正在尝试在 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。帮助

【问题讨论】:

【参考方案1】:

您不能直接通过装饰器执行此操作。装饰器在类创建(而不是实例化)时被调用,所以我们所能做的就是改变类本身以满足我们的需要。

一种选择是将字段转换为属性并在 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);

很遗憾,无法从属性描述符中截取类构造函数。

【讨论】:

以上是关于使用属性装饰器来启动一个类的主要内容,如果未能解决你的问题,请参考以下文章

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

react——@修饰器——高阶组件的使用——通过装饰器来调用高阶组件——简单修改样式

在 Python 中,是不是可以使用相同的装饰器来装饰类和非类方法?

如何使用@property 装饰器来限制列表中的值