我知道我们可以使用Dart中的工厂创建单例类。但我碰巧回想起在某个地方读书,使用type(MyController)或类型(MyServiceClass)注册的类本身就是单例。
这是真的吗?如果是这样,它是仅适用于使用type(MyController)注册的类,还是使用注释@NgController等。这对我们编写的服务和工厂类有何影响。
此外,我在哪里可以找到解释相同的文档或链接。
答案 0 :(得分:3)
简短回答:不,NgControllers不是单身人士。长篇答案讨论了层次依赖注入和AngularDart模板编译器。
依赖注入(DI)
DI的基本设置是为DI系统注册的每种类型创建单个实例。在创建进样器之前,通过模块注册类型。创建注入器后,它将按需创建实例。
var injector = new Injector([
new Module()
..type(SomeClass)
..value(AnotherClass, new AnotherClass('toplevel'))]);
分层DI
AngularDart使用分层DI系统,它允许我们“阴影”#34;通过创建子注入器在进样器中输入类型。考虑
var childInjector = new Injector.fromParent([
new Module()..type(AnotherClass, implementedBy: AnotherSubclass)], injector);
如果从第一个进样器获得AnotherClass类型,您将获得"顶级" AnotherClass。从childInjector,您将获得AnotherSubclass的实例。但是,两个注入器共享第一个注册类型SomeClass的实例。
AngularDart的编译器
当Angular实例化模板时,它会遍历模板的DOM,寻找与指令选择器匹配的元素。当它找到一个与一个或多个指令匹配的元素时,它将为该元素创建一个新的子注入器。然后它使用新的子注入器来创建指令。
这意味着您有一个镜像注入结构,它反映了DOM结构。当为两个不同的元素创建相同的指令时,它们是在两个不同的注入器中创建的。
但是,由于指令可以从注入器请求其他指令(比如在它们的构造函数中),如果在共享父注入器上创建了第二个指令,则两个指令可能共享同一个实例。
指令选择器和重要类型
创建编译器时,它会获取所有已注册指令及其选择器的列表。它通过向DI系统询问所有使用@NgAnnotation注释的类型来实现这一点。 @NgDirective,@ NgComponent,@ NgController都是@NgAnnotation的子类型,所以它们都包含在该列表中。
这就是为什么你可能在同一个模块中有两个类型MyController和MyService,但只有一个MyController可供编译器使用。
答案 1 :(得分:2)
Angular 2 Dart
DI为每个提供商维护一个实例。
DI从一个组件的提供者查看,该组件向父组件的提供者请求依赖关系(构造函数参数),然后是父组件的父组件,直到根组件,然后再向{{{ 1}}和Angular本身提供的提供程序。
注入这种方式的第一个提供者的实例。
如果有更多提供者,则会有更多实例。
如果在bootstrap(AppComponent, [/* providers */])
中注册了提供程序,则每个组件实例上的每个提供程序都有不同的实例。
Angular 1 Dart
每次请求特定类型的实例时,从同一个注射器获得相同的实例
但是在角度上,喷射器是分层的(类似于范围)
当您请求类型时,向上查找层次结构以查找已注册该类型的注入器,并且此注入器每次都返回相同的实例。
如果将控制器的相同选择器应用于多个DOM元素,则每次都会获得一个新的控制器实例,因为会创建一个新的注入器实例,该实例会获得一些类似于控制器和控制器应用的元素的类型。当您请求已注册的类型时,该注入器将返回其自己的实例。