【问题标题】:How to instantiate angular components with new keyword?如何使用 new 关键字实例化角度组件?
【发布时间】:2021-05-16 19:12:02
【问题描述】:

如何用new关键字实例化角度组件?

将以下想象成一个无模板的组件:

import { Component } from '@angular/core';

@Component({
  selector: 'my-component',
})
export class MyComponent {
constructor(private myService: MyService)
}

我知道只有在模板中找到选择器标签时才会实例化角度组件。

但是…… 如何使用 new 关键字实例化上述内容? 因为我的组件不需要模板。

但它应该是带有@component 装饰器的角度组件。 (因为我需要依赖注入的特性)

但问题是当我创建一个新组件时,如下所示:

const comp = new MyComponent()

它还要求在实例化时也将服务实例传递给它的构造函数。像这样”

const comp = new MyComponent(new MyService())

当我们再次传入的服务依赖于其他服务时,就变得更加困难了。

像这样……

const comp = new MyComponent(new MyService(new AnotherService(new YetAnotherService(... so on))))

那么有解决办法吗?

Angular 的 DI 很不错。因为我们没有任何类似上述的问题。它会自动创建所有注入的服务。 new 关键字也可以做到这一点。

注意我尝试使用普通的打字稿类。但我还是不喜欢。我想自己使用角度组件。

这可能吗?

【问题讨论】:

  • 有没有办法...请告诉我!!!
  • 为什么要这么做?有什么特别的原因吗?
  • 是的,这都是关于画布的。所以我不需要任何模板。但是我仍然需要依赖注入的功能,因为我的组件依赖于很多服务。
  • 所以我需要使用新关键字创建组件的能力。但这样做的问题是我将不得不手动传递服务。
  • 这不是唯一的问题 - 管理这些服务的实例可能很困难。注入器保留它们,因此组件可以共享相同的实例

标签: angular


【解决方案1】:

我强烈建议不要这样做。 Angular 不是为此而生的,更改检测可能无法正常工作,您必须自己管理组件。

不过不管怎样,如果要动态创建组件,可以使用ComponentFactoryResolver

import { Component, ComponentFactoryResolver, Injector, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'hello'
})
export class HelloComponent  {
  @Input() get name(): string { return this._name; }
  set name(value: string) {
    this._name = value;
    this.nameChange.emit(value);
  }
  private _name: string;

  @Output() nameChange = new EventEmitter<string>();
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html'
})
export class AppComponent  {
  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector
  ) { }

  ngOnInit() {
    const factory = this.componentFactoryResolver.resolveComponentFactory(HelloComponent);
    const helloRef = factory.create(this.injector);

    const hello = helloRef.instance;

    // Subscribe to output
    const subscription = hello.nameChange.subscribe(name => console.log('name changed', name));

    // Set name input
    hello.name = 'Hello!';

    // When you are done with the component, it must be destroyed
    subscription.unsubscribe();
    helloRef.destroy();
  }
}

在您的情况下没关系,因为您没有模板,但如果您需要在动态创建的组件中进行更改检测,则需要将它们附加到应用程序:

export class AppComponent  {
  constructor(
    // ...
    private applicationRef: ApplicationRef
  ) { }

  ngOnInit() {
    // create helloRef ...
    this.applicationRef.attachView(helloRef.hostView);

    // ...

    // Destroy the component
    this.applicationRef.detachView(helloRef.hostView);
    helloRef.destroy();
  }
}

【讨论】:

  • 那么我将如何进行属性绑定@Input@Output。如何将参数传递给组件的构造函数?
  • 我用输入和输出的例子更新了答案。你不能直接将参数传递给构造函数,它会使用 Angular 依赖注入,所以你可以在 AppModule 中提供服务并将它们注入到组件中。
猜你喜欢
  • 2019-02-18
  • 2012-03-06
  • 2021-07-11
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 2020-07-19
相关资源
最近更新 更多