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

为什么必须提供angular2组件构造函数参数,angular,typescript,constructor,angular-components,Angular,Typescript,Constructor,Angular Components,我是个新手。在编写Heros教程时,我注意到组件构造函数参数的类型必须是依赖项。换句话说,我必须将其包含在providers数组中 例如: import { SomeServiceClass } from '...'; @Component({ ... }) export class MyComponent implements OnInit { constructor(input1: SomeServiceClass) { } ngOnInit() { } } 除非我在p

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

例如:

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

  constructor(input1: SomeServiceClass) { }

  ngOnInit() {
  }
}
除非我在providers数组中包含SomeServiceClass,否则此代码将无法工作。我尝试了
input1:string
。它也不起作用!我相信这是完全有效的打字脚本代码。问题一定是angular2实例化组件类的方式

问题1:如何通过Angular实例化组件分类

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

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

除非我在providers数组中包含SomeServiceClass,否则此代码将无法工作。我试着输入1:string。它也不起作用!我相信这是完全有效的打字脚本代码。问题一定是angular2实例化组件类的方式

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

作为证据,他确实做到了这一点

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

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

@autoinject export class MyComponent {
  constructor(input1: SomeServiceClass) {}
}
它是有效的

组件是如何通过Angular实例化的

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

JavaScript中的类实际上是一个构造函数,构造函数实际上是一个美化的工厂函数,工厂函数实际上是一个美化的函数

这是什么意思

这意味着Angular(和大多数DI框架)只需在第一次请求服务时创建服务实例,方法是使用
new
调用提供的类

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

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

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

非常好的答案!这也让我思考如何初始化角度应用程序。现在我只知道模块、服务和组件。你能解释一下它们的运行顺序吗?我不确定我是否理解,你是说渴望还是懒惰?因为angular有这么多组件(不是说angular组件),必须有一个特定的顺序来运行代码的这些部分。例如,它可以先运行一个服务来创建依赖项,然后运行组件来使用该服务。或者,它可以先运行组件,然后在需要服务时运行服务。这是我提到的两个场景,即运行顺序。这有意义吗?有点。每个
injector
在实例化依赖组件/路由/服务时创建服务。所以依赖项在第一次需要时被初始化,然后被缓存。@zhangjizhou这有意义吗?
class C {}