如何使用 new 关键字实例化角度分量?

mx_*_*ode 5 angular

如何使用 new 关键字实例化角度分量?

想象一下以下作为无模板组件:

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

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

Run Code Online (Sandbox Code Playgroud)

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

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

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

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

const comp = new MyComponent()
Run Code Online (Sandbox Code Playgroud)

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

const comp = new MyComponent(new MyService())
Run Code Online (Sandbox Code Playgroud)

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

像这样...

const comp = new MyComponent(new MyService(new AnotherService(new YetAnotherService(... so on))))
Run Code Online (Sandbox Code Playgroud)

那么有解决方法吗?

Angular 的 DI 很好。因为我们没有像上面这样的问题。它会自动创建所有注入的服务。那么用new关键字可以吗?

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

那可能吗?

Yan*_*p-H 3

我强烈建议不要这样做。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();
  }
}

Run Code Online (Sandbox Code Playgroud)

对于您的情况来说并不重要,因为您没有模板,但是如果您需要在动态创建的组件中进行更改检测,则需要将它们附加到应用程序:

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();
  }
}

Run Code Online (Sandbox Code Playgroud)