Angular Module
Angular是模块化的,模块是Angular应用的基本构建块,每个Angular应用都至少有一个模块,即根模块,Angular模块是一个带有@NgModule装饰器的类。
模块是一个逻辑单元,是一个自我完备的功能集合,它可以包含组件、服务、指令、管道等,模块可以导入其他模块,也可以导出组件、指令、管道等供其他模块使用,模块还可以提供Service。
以一个电商网站App为例,可以包含如下模块:登录模块(包含登录,注册,找回密码等功能),购物模块,订单模块,支付模块等等。
Generate Angular module with Angular CLI
使用Angular CLI生成一个新的模块,运行如下命令:
1 | ng generate module moduleName // or ng g m moduleName |
NgModule的组成
以下是一个典型的入口模块的代码:
1 | ({ |
declarations
declarations属性用来声明属于该模块的组件、指令、管道等,这些组件、指令、管道等只能在该模块中使用,其他模块不能使用。
declarations只能包含component,directive,pipe.component,directive,pipe- 统称为declarable, 每个declarable只能隶属于一个NgModule,如果在多个NgModule中导入同一个declarable,那么会出现如下错误:
1 | xxx is declared in multiple Angular modules: AppModule and AppContentModule |
imports
imports属性用来导入其他模块,一经导入,那么被导入的模块中包含的组件、指令、管道等可以在当前模块中使用。比如当前模块依赖另一个模块A,那么要把模块A导入到当前模块中,这样当前模块才可以使用模块A中的组件、指令、管道等。
imports只能包含module, 或者standalone component.
providers
providers属性用来声明该模块中的服务,这些服务可以在该模块中使用,也可以在该模块导入的其他模块中使用。(我在现实中看见有人把Component放到providers中也能work,这不是好的编程习惯。)
exports
exports属性用来声明该模块中导出的组件、指令、管道等,这些导出的组件、指令、管道等可以在该模块导入的其他模块中使用。注意导出的组件、指令、管道等必须同时在declarations属性中声明。
也就是说exports是declarations的子集。
Angular应用的主模块app.module.ts中的exports属性是空的,因为根模块中的组件、指令、管道等都是可以在其他模块中使用的,所以不需要导出。
bootstrap
bootstrap属性用来声明该模块的根组件,根组件是Angular应用的入口组件,一个Angular应用只能有一个根组件,根组件只能在根模块中声明。bootstrap中声明的组件会插入到index.html中的<app-root></app-root>标签中。
注意:bootstrap中可以指定多个组件,这些组件会被插入到index.html中,index.html中根据组件的选择器加在不同的组件。
1 | <!--index.html--> |
1 | // app.module.ts |
注意: 只有根模块才需要声明根组件,其他模块不需要声明根组件。所以除了app.module.ts之外,其他的module都不需要声明bootstrap属性。
component and module
在Angular standalone component出现以前,任何一个component都必须隶属于一个module。但是在Angular standalone component出现以后,component就可以不用隶属于一个module了,这种component称为standalone component,也就是独立的component。
详情请看Angular Standalone Component
How Angular module identifies components?
Angular module是如何识别Component的呢?对于非standalone component,Angular module是通过declaration来标记的。对于standalone component,Angular module是通过imports来标记的。
非独立组件还分为两种情况,有对应的angular module或者没有对应的angular module
- 有
angular module- 当前module需要导入对应的angular module,才能使用导入module中的component。(待使用的component需在其module中exports数组中导出) - 没有
angular module- 则需要将component声明在当前module的declarations中。
Example
假设我们需要定义如下两个组件, 这两个组件都有对应的module
ProductHomeModule包含ProductHomeComponent- 产品首页, 该组件内部又调用了ProductDetailComponentProductDetailModule包含ProductDetailComponent- 产品详情页
首先,需要在ProductDetailModule中声明ProductDetailComponent,并导出ProductDetailComponent。
1 | // product-detail.module.ts |
然后,需要在ProductHomeModule中导入ProductDetailModule,这样ProductHomeComponent就可以使用ProductDetailComponent了。
1 | // product-home.module.ts |
最后,在ProductHomeComponent模板中使用ProductDetailComponent。
1 | <!-- product-home.component.html --> |