共计 1865 个字符,预计需要花费 5 分钟才能阅读完成。
前言
问题起因是因为在 GriderService 中遗记给根模块提供注入。
即没有写
@Injectable({providedIn: 'root'})
手动注入
过后想着,能不能单纯 在组件中应用 provide GriderService使这个组件失常用 service 提供的服务. 就像上面这样:
providers: [
{provide: GriderService}
]
但事实上可行性不大。
因为 GriderService 的函数中 同样须要依赖注入 HttpClient,如下
constructor(protected httpClient: HttpClient) { }
所以,手动注入 GriderService 须要 先手动注入 HttpClient。
所以我尝试着手动注入了 HttpClient。并且如果 new 一个 HttpClient 的话,须要 先 new 一个 HttpHandler,这是 Httpclient 的构造函数所须要的。或者我应该这么做:
let httpHandler = new HttpHandler();
let httpClient = new HttpClient(httpHandler);
然而,实际上 HttpHandler 是抽象类,并不能被实例化。
最初没胜利,并且在 google 上查找也没有比依赖注入更不便的了。我的确应该应用依赖注入。DI 是 Angular 中的一个基本概念,也是使该框架如此有用的起因之一。
依赖注入
@Injectable() 装璜器标识服务类 。该 providedIn 属性配置 指定的 ModuleInjector,这里的 root 会把让该服务在 root ModuleInjector 上可用
长处
用 @Injectable() 的 providedIn 属性 优于 @NgModule() 的 providers 数组,不仅在于它 方便快捷 ,还因为应用 @Injectable() 的 providedIn 时,优化工具能够进行 摇树优化 (Tree Shaking)简略说就说通过 Tree Shaking,不该留在代码中的 多余代码,则会被摇掉。
root
root 实际上是 AppModule 的别名,示意根模块, 咱们因而不须要额定导入 AppModule, 所有的模块原则上都属于根模块的子模块,所以所有的子模块都能够无条件的应用 root 根模块上的资源
对于注射器
在 root ModuleInjector 之上还有两个注入器,一个是额定的 ModuleInjector,一个是 NullInjector()
为了了解这张图,先大抵理解一下从 angular 启动。
angular 启动
每一个 Angular 利用都以 main.ts 文件作为终点。(main.cs 目前位于我的项目的 src 文件夹下,与 app 文件夹是同一级)
main.cs 中最要害的是这两行代码:
1.platformBrowserDynamic() 办法创立一个由 PlatformModule 配置的注入器,简略来说就是浏览器平台的工厂函数, 执行会返回 浏览器平台的实例。
2.bootstrapModule() 办法会创立一个 由 AppModule 配置 的注入器作为平台注入器的 子注入器。也就是 root ModuleInjector
3. 同时 bootstrapModule 启动 app 文件夹下的 AppModule 后,Angular 会去查看模块 AppModule 的 bootstrap 属性,该模块是用来启动程序的:
@NgModule({imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
依赖注入服务流程
大抵了解了启动流程之后,咱们再联合方才那张图来看就很好了解了。
1.platformBrowserDynamic创立一个由 PlatformModule 配置的注入器Modele Injector。该注入器蕴含特定平台的依赖项
2. 应用 bootstrapModule 办法,创立root ModeleInjector。
3.root ModeleInjector启动之后。若某个 service 能够给 root 提供服务,即
该 service 依赖注入 root,root 模块就能够应用该 service 提供的服务。
图例
至于最顶层的 NullInjector(),它是 树的顶部 。如果你在树中向上走了很远,以至于要在 NullInjector() 中寻找服务,那么 除非应用 @Optional(),否则将收到谬误音讯,因为最终所有货色都将以 NullInjector() 完结并返回谬误。