Angular 模块漫谈

Photo by Vanessa Lang on Unsplash

模块是 一个 Angular 应用组织的重要一环,通过模块之间的导入导出,我们可

以把复杂的功能分解到各个模块中,增强了代码的复用性可维护性。但是这也

引入了一定的学习复杂度。本教程从 Angular 模块入手,将 Angular 应用组

织方式和模块中资源的可见性做了详细的解释。读完本文,相信会对 Angular

有更新的认识。

约定

为了不引起歧义,方便描述,下面所有的描述遵循这样的规则。

模块自身定义的组件、管道、指令以及服务统称为模块本身的——资源。

应用的组成

模块是如何组织本模块与外部模块资源的?我们可以仔细观察下图。

可以清楚的看到,一个 Angular 应用由多个模块构成。通过 imports 关键字,

使得每个模块可以复用其他模块导出的资源。imports 就像针线一般将各个模

块串联起,从而构成一个复杂的 Angular 应用。

本地资源可见性

declarations 声明的资源其作用域被限制在本模块中。若想要在其他模块中使

用这些基础组件,必须使用 exports 进行导出。否则即使 import 进来,模块

内部的资源对于其他模块仍然不可见。

服务的可见性

但是模块中 providers 中指定的服务非常特殊。由于服务是在应用的整个生命

周期生成一个单一实例,因此一旦模块中提供了服务并且此模块通过 imports

进入了应用,那么就会应用在启动时生成一个单一的服务实例。它的可见性就

是全局的。这意味着任何组件都可以使用这个服务。

学会使用外部模块

由于服务与其他基础组件的作用域不同。因此当导入一个外部模块时,你可以

记住这么三条原则:

一、如果外部模块不含服务,仅仅包含组件类 ,那么非常容易!你只要在这个

组件对应的模块中导入这个外部模块即可!

二、如果该外部模块既包含服务又包含其他资源,那么就只须在 AppModule

中导入服务,而在特性模块中导入外部模块的其他资源。

一般来说,这种含服务又包含组件类的第三方模块会提供静态方法 forRoot 和

forChild 方法。在 AppModule 中我们使用 forRoot 注册服务,在特性模块中

使用 forChild 导入组件类。

三、如果该外部模块只包含服务。比如 HttpClientModule 这类的外部模块,

我们只需要在 AppModule 中导入一次,生成单一服务实例即可。

常见的例子——RouterModule

就常见的 RouterModule 来说。我们会使用 RouterModule 提供的指令

<router-outlet> 来动态生路由页面 ,也要使用服务 ActivatedRoute 来获取路

由参数或者 Resovler 数据。我们只要在 AppModule 中使用 forRoot 方法来

提供全套功能包含服务。

而在其他特性模块中就只要使用 forChild 导入组件类即可(不需要服务)。

参考资料

Understanding Angular modules (NgModule) and their scopes

发表评论

电子邮件地址不会被公开。 必填项已用*标注