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

zha*_*hou 3 constructor typescript angular-components angular

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

例如:

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

  constructor(input1: SomeServiceClass) { }

  ngOnInit() {
  }
}
Run Code Online (Sandbox Code Playgroud)

除非我在providers数组中包含SomeServiceClass,否则此代码不会起作用.我试过了input1: string.它既不起作用!我相信它是完全有效的打字稿代码.问题必须是angular2实例化组件类的方式.

问题1:如何将组件分类实际由Angular实例化?

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

问题2:angular是否创建了每个组件使用的一个服务实例,或者为每个组件生成一个实例?

Alu*_*dad 6

除非我在providers数组中包含SomeServiceClass,否则此代码无效.我试过input1:string.它既不起作用!我相信它是完全有效的打字稿代码.问题必须是angular2实例化组件类的方式.

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

作为证据,Aurelia正是如此.

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

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

@autoinject export class MyComponent {
  constructor(input1: SomeServiceClass) {}
}
Run Code Online (Sandbox Code Playgroud)

它有效.

如何将组件分类实际由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;
     }
  });
}
Run Code Online (Sandbox Code Playgroud)

angular是否创建了每个组件使用的一个服务实例,或者为每个组件生成一个实例?

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

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

但是,Angular中也存在不同的隐式和显式行为.

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

最后,组件可以providers@Component元数据中明确声明自己的组件.执行此操作的任何组件都将具有由该组件的所有实例创建和共享的新服务实例.

注意:只是在你说时要具体

我注意到组件构造函数参数的类型必须是依赖项.

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

class C {}
Run Code Online (Sandbox Code Playgroud)

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