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
- 产品首页, 该组件内部又调用了ProductDetailComponent
ProductDetailModule
包含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 --> |