为什么必须提供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
添加到包含一些 ngModule
的 providers
数组的原因很简单。 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
.
我是 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
添加到包含一些 ngModule
的 providers
数组的原因很简单。 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
.