如果我没有在providers数组中包含SomeServiceClass,这段代码将无法工作。我尝试了input1:string,它也不起作用!我相信这是完全有效的typescript代码。问题一定是angular2实例化组件类的方式。
你需要将SomeServiceClass
添加到某个ngModule
的providers
数组中的原因很简单。Angular选择不基于代码结构执行任何依赖性分析。他们可以使用注入组件中的ES模块导入来解决依赖关系并自动注册它。
证据是,Aurelia正是这样做的。
换句话说,在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);
const newDependency = new Dep(...requiredDependencies.map(resolveDependencies));
injectorCache.push(newDependency);
return newDependency;
}
});
}
Angular会为每个组件生成一个服务实例还是只创建一个实例供所有组件使用?这有点棘手,默认情况下,每个应用程序只创建一个实例。这是应用程序级别的单例,所有请求它的组件都会收到相同的实例。但是,Angular也有不同的隐式和显式行为。如果一个懒加载的ngModule在其提供商数组中列出了相同的服务,则会创建第二个实例,并且该实例将由懒加载模块的子代共享。这实际上是一种过度简化,但已经令人困惑,并且由于模块是否被延迟加载是由其消费者确定的,因此可能会导致严重而微妙的错误。最后,组件可以在@Component元数据中显式声明自己的提供商。任何这样做的组件都将创建一个新的服务实例,并由该组件的所有实例共享。注意:当您说“我注意到组件构造函数参数的类型必须是依赖项”时,请具体说明。
你的理解不完全正确。依赖项不是“类型”,它们是“值”。TypeScript类型在编译时完全被擦除,实际注入的是值。类是一个值。
class C {}
但 TypeScript 也会从声明中推断出一些类型的存在。但注入的是值
C
,而不是类型
C
。