Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 使用类装饰器向新属性添加装饰器_Angular_Typescript - Fatal编程技术网

Angular 使用类装饰器向新属性添加装饰器

Angular 使用类装饰器向新属性添加装饰器,angular,typescript,Angular,Typescript,我想知道的几乎都在书名里。 我想知道如何添加一个新属性,它有自己的decorator和一个类decorator 我想创建一个类装饰器Api(string[]),它公开类装饰器中列出的类方法。 为此,我想从Angular发出一个带有EventEmitter的事件,为此,我必须将@Output()装饰器添加到一个新属性中 我可以吗 下面是一个示例:我只是有一个MyClass,其中包含process、open和close方法。 我想创建decorator(s?)来公开我想要的任何方法(这里是open和

我想知道的几乎都在书名里。 我想知道如何添加一个新属性,它有自己的decorator和一个类decorator

我想创建一个类装饰器Api(string[]),它公开类装饰器中列出的类方法。 为此,我想从Angular发出一个带有
EventEmitter
的事件,为此,我必须将
@Output()
装饰器添加到一个新属性中

我可以吗

下面是一个示例:我只是有一个MyClass,其中包含process、open和close方法。 我想创建decorator(s?)来公开我想要的任何方法(这里是open和close)。我想象了一个类装饰器,它添加了
api
属性和一个方法装饰器来公开一个方法,也许吧

class MyClass {
  @Output() api = new EventEmitter();

  $exposedMethods: object = {};

  constructor() {
    this.$exposedMethods = {
      open: this.open.bind(this),
      close: this.close.bind(this)
    };
    this.api.emit(this.$exposedMethods);
  }

  process() {

  }

  open() {
    // stuff...
  }

  close() {
    // stuff...
  }
}

好的,所以请做好准备,因为这是一个很难掌握的概念

这里有现场演示:

守则:

从'@angular/core'导入{Component,Input,Output,EventEmitter};
const Expose:(方法:string[])=>ClassDecorator=(方法)=>{
返回组件=>{
for(const方法中的方法){
const eventEmitterName=`${method}发射器`;
prototype[eventEmitterName]=新的EventEmitter();
const outputFactory=输出(方法);
const orgFn=组件.原型[方法];
component.prototype[方法]=(…参数)=>{
orgFn(…args);
prototype[eventEmitterName].emit();
}
outputFactory(component.prototype,eventEmitterName);
}
}
}
@组成部分({
选择器:“你好”,
模板:`Emit a open event`,
样式:[`h1{font-family:Lato;}`]
})
@公开(['open']))
导出类HelloComponent{
@Input()名称:string;
开(){
log('单击按钮,现在发出事件');
}
ngOnInit(){}
}
类装饰器是函数。
在您的例子中,这是一个类装饰器工厂:您提供了参数,它应该返回一个类装饰器。这是您可以看到的签名:

const Expose: (methods: string[]) => ClassDecorator = (methods) => { ... }
它声明
Expose
为返回类装饰器的工厂。您的工厂接受方法列表作为参数

现在,这个工厂需要返回一个类装饰器。类装饰器是将组件本身作为唯一参数的函数。这是电话线

return component => { ... }
它返回一个符合
ClassDecorator
签名的函数

之后,您需要重写每个方法。因此,您将使用一个简单的循环对其进行循环

在循环中,我们将创建一个新的事件发射器。为了简单起见,我们将使用名称
[method]Emitter
。所以我们从创造圣名开始:

const eventEmitterName = `${method}Emitter`;
完成后,我们将其绑定到组件的原型:

component.prototype[eventEmitterName] = new EventEmitter();
现在有了事件发射器

之后,您需要将输出装饰器绑定到它。如果您按照前面的步骤操作,您将了解
输出实际上也是一个工厂。这意味着它返回一个
MethodDecorator
函数,其签名为

(component, methodKey) => { ... }
(还有第三个参数叫做描述符,但您不需要它,所以我将忽略它)

一旦知道这一点,我们将获取我们的方法的工厂结果:

const outputFactory = Output(method);
这将创建一个以您的方法命名的输出(这里是
open

完成后,我们将重写给定的方法,在其处理完成时发出事件

这是基本的JS函数重写:

const orgFn = component.prototype[method];

component.prototype[method] = (...args) => {
  orgFn(...args);
  component.prototype[eventEmitterName].emit();
}
在最后一行,我们通过先前创建的事件发射器发射事件

现在,我们所要做的就是将这个事件发射器绑定到我们的组件。为此,我们只需调用由输出工厂创建的方法decorator

outputFactory(component.prototype, eventEmitterName);
现在,你的装饰师已经完成并开始工作了。正如您在stackblitz上看到的,正在运行
open
函数中的代码,然后一旦运行,将运行应用程序组件模板中
(open)
输出的代码


瞧好的,所以做好准备,因为这是一个非常难理解的概念

这里有现场演示:

守则:

从'@angular/core'导入{Component,Input,Output,EventEmitter};
const Expose:(方法:string[])=>ClassDecorator=(方法)=>{
返回组件=>{
for(const方法中的方法){
const eventEmitterName=`${method}发射器`;
prototype[eventEmitterName]=新的EventEmitter();
const outputFactory=输出(方法);
const orgFn=组件.原型[方法];
component.prototype[方法]=(…参数)=>{
orgFn(…args);
prototype[eventEmitterName].emit();
}
outputFactory(component.prototype,eventEmitterName);
}
}
}
@组成部分({
选择器:“你好”,
模板:`Emit a open event`,
样式:[`h1{font-family:Lato;}`]
})
@公开(['open']))
导出类HelloComponent{
@Input()名称:string;
开(){
log('单击按钮,现在发出事件');
}
ngOnInit(){}
}
类装饰器是函数。
在您的例子中,这是一个类装饰器工厂:您提供了参数,它应该返回一个类装饰器。这是您可以看到的签名:

const Expose: (methods: string[]) => ClassDecorator = (methods) => { ... }
它声明
Expose
为返回类装饰器的工厂。您的工厂接受方法列表作为参数

现在,这个工厂需要返回一个类装饰器。类装饰器是将组件本身作为唯一参数的函数。这是电话线

return component => { ... }
它返回一个符合
ClassDecorator
签名的函数

之后,您需要重写每个方法。因此,您将使用一个简单的循环对其进行循环

在循环中,我们将创建一个新的事件发射器。为了简单起见,我们将使用名称
[method]Emitter
。因此,我们从创造神圣的世界开始