1

angular 依赖注入 - SegmentFault 思否

 2 years ago
source link: https://segmentfault.com/a/1190000040920582
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

angular 依赖注入

发布于 11 月 6 日

问题起因是因为在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是抽象类,并不能被实例化。
image.png

最后也没查到什么可行性的代码。我们应该使用依赖注入。DI是 Angular 中的一个基本概念,也是使该框架如此有用的原因之一。

image.png

@Injectable() 装饰器标识服务类。该 providedIn 属性配置指定的 ModuleInjector,这里的 root 会把让该服务在 root ModuleInjector 上可用

@Injectable() 的 providedIn 属性优于 @NgModule() 的 providers 数组,不仅在于它方便快捷,还因为使用 @Injectable() 的 providedIn 时,优化工具可以进行摇树优化(Tree Shaking)简单来说 经过Tree Shaking,不该留在代码中的多余代码,则会被摇掉

root 实际上是 AppModule 的别名,表示根模块,我们因此不需要额外导入 AppModule,所有的模块原则上都属于根模块的子模块,所以所有的子模块都可以无条件的使用root根模块上的资源
image.png

关于注射器

在 root ModuleInjector 之上还有两个注入器,一个是额外的 ModuleInjector,一个是 NullInjector()

image.png

为了理解这张图,先大致了解一下从angular启动。

angular启动

每一个 Angular 应用都以 main.ts 文件作为起点。(main.cs目前位于项目的src文件夹下,与app文件夹是同一级)
image.png

main.cs中最关键的是这两行代码:image.png

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 {}

依赖注入服务流程

大致理解了启动流程之后,我们再结合刚才那张图来看就很好理解了。
image.png

1.platformBrowserDynamic创建一个由 PlatformModule 配置的注入器Modele Injector。该注入器包含特定平台的依赖项

2.使用bootstrapModule方法,创建root ModeleInjector。

3.root ModeleInjector启动之后。若某个service可以给root提供服务,即
该service依赖注入root,root模块就可以使用该service提供的服务
image.png

图例

image.png

至于最顶层的NullInjector(),它是树的顶部。如果你在树中向上走了很远,以至于要在 NullInjector() 中寻找服务,那么除非使用 @Optional(),否则将收到错误消息,因为最终所有东西都将以 NullInjector() 结束并返回错误

总结:DI增加了angular应用程序的灵活性和模块化,它可以使得我们这样方便地使用

constructor(private http: HttpClient)

假如没有Angular DI机制,我们必须手动提供HttpClient来创建我们自己的服务。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK