为什么必须提供angular2组件构造函数参数

why angular2 component constructor parameters must be provided

我是 Angular 的新手。当我在做 Heros 教程时,我注意到组件构造函数参数的类型必须是依赖项。换句话说,我必须将它包含在 providers 数组中。

例如:

import { SomeServiceClass } from '...';
@Component({
  ...
})
export class MyComponent implements OnInit {

  constructor(input1: SomeServiceClass) { }

  ngOnInit() {
  }
}

除非我在 providers 数组中包含 SomeServiceClass,否则此代码将无法运行。我试过了input1: string。也不行!我相信这是完全有效的打字稿代码。问题一定是 angular2 实例化组件 classes 的方式。

问题 1:组件 class 是如何被 Angular 实际实例化的?

而且,由于我从未实例化服务 class,我无法想象哪个服务 class 实例被传递给组件构造函数。

问题 2:angular 是创建一个服务实例供每个组件使用,还是为每个组件生成一个实例?

This code is not going to work unless I include SomeServiceClass in providers array. I tried input1: string. It doesn't work neither! I believe it is totally valid typescript code. The problem must be the way angular2 instantiates the component classes.

您需要将 SomeServiceClass 添加到包含一些 ngModuleproviders 数组的原因很简单。 Angular选择不进行任何基于代码结构的依赖分析。他们本可以在注入组件中使用 ES 模块导入来解决依赖关系并自动注册它。

作为证据,Aurelia 确实如此。

换句话说,在 Aurelia 中,以下足以注入和使用依赖项

import {autoinject} from 'aurelia-framework';
import {SomeServiceClass} from '...';

@autoinject export class MyComponent {
  constructor(input1: SomeServiceClass) {}
}

而且有效。

How are component classed actually instantiated by Angular?

And, since I never instantiate service class, I can't imagine which service class instance is passed to component constructor.

JavaScript中的一个class真的是构造函数,构造函数真的是美化了的工厂函数,工厂函数真的是美化了的函数。

这是什么意思?

这意味着 Angular(和大多数 DI 框架)在首次请求时通过使用 new.[=28 调用提供的 class 来简单地创建一个服务实例=]

此类代码的简化版本可能如下所示

function instantiateComponent<T>(Component: new (...args: any[]) => T) {
  const requiredDependencies = resolveDependencies(Component);

  return new Component(...requiredDependencies);
}

function resolveDependencies(Dep: new (...args: any[]) => any): object[] {
  const requiredDependencies = metaDataUtils.getDependencies(Dep);
  
  return requiredDependencies.map(Dep => {
     const alreadyCreatedDependency = injectorCache.find(dep => dep instanceof Dep);
     
     if(alreadyCreatedDependency !== undefined) {
       return alreadyCreatedDependency;
     }
     else {
       const requiredDependencies = metaDataUtils.getDependencies(Dep);
       
       // resolution is recursive
       const newDependency = new Dep(...requiredDependencies.map(resolveDependencies));

       injectorCache.push(newDependency);

       return newDependency;
     }
  });
}

Does angular create one instance of service to be used by every component or it generates one instance for each component?

这个有点棘手,默认情况下每个应用程序只创建一个实例。

这是一个应用程序级别的单例,所有请求它的组件都会收到相同的实例。

但是,Angular 中也有不同的隐式和显式行为。

如果延迟加载 ngModule 在其 providers 数组中列出相同的服务,将创建第二个实例,并且该实例将由延迟加载模块的子项共享。这实际上是一种过度简化,但它已经令人困惑,并且考虑到模块是否延迟加载是由其消费者决定的,它可能导致严重和微妙的错误。

最后,组件可以在 @Component 元数据中显式声明自己的 providers。这样做的任何组件都将创建一个新的服务实例,并由该组件的所有实例共享。

注:只是说的具体点

I noticed type of component constructor parameters must be a dependency.

你并不完全正确。依赖关系不是类型,而是。 TypeScript 类型在编译时被完全擦除,实际注入的是值。一个class是一个值

class C {}

但是 TypeScript 也会从其声明中推断出某些类型的存在。但是注入的是值C,而不是类型C.