(三)创建功能模块
来源:互联网 发布:深圳淘宝免费运营 编辑:程序博客网 时间:2024/06/06 03:37
原文链接:https://angular-2-training-book.rangle.io/handout/modules/feature-modules.html
当我们的根模块开始增长时,最开始显而易见的是,某些元素(组件,指令等)在某方面相关联,几乎感觉他们属于可以被“插入”的库。
在我们前面的例子中,我们开始看到了。 我们的根模块具有组件,管道和服务,其唯一目的是处理信用卡。 如果我们将这三个元素提取到自己的特征模块 ,然后将其导入到我们的根模块会怎么样?
我们要做到这一点。 第一步是创建两个文件夹,以将属于根模块的元素与属于功能模块的元素区分开来。
.├── app│ ├── app.component.ts│ └── app.module.ts├── credit-card│ ├── credit-card-mask.pipe.ts│ ├── credit-card.component.ts│ ├── credit-card.module.ts│ └── credit-card.service.ts├── index.html└── main.ts
请注意每个文件夹如何拥有自己的模块文件: app.module.ts和credit-card.module.ts 。 我们首先关注后者。
credit-card/credit-card.module.ts
import { NgModule } from '@angular/core';import { CommonModule } from '@angular/common';import { CreditCardMaskPipe } from './credit-card-mask.pipe';import { CreditCardService } from './credit-card.service';import { CreditCardComponent } from './credit-card.component';@NgModule({ imports: [CommonModule], declarations: [ CreditCardMaskPipe, CreditCardComponent ], providers: [CreditCardService], exports: [CreditCardComponent]})export class CreditCardModule {}
我们的功能CreditCardModule它非常类似于根模块AppModule,但还是有一些重要的区别:
*我们没有导入BrowserModule而是CommonModule 。 如果我们在这里可以看到BrowserModule的文档,我们可以看到它是通过许多其他服务重新导出CommonModule ,有助于在浏览器中渲染Angular应用程序。 这些服务将我们的根模块与特定平台(浏览器)相结合,但我们希望我们的功能模块是独立于平台的。 这就是为什么我们只在那里导入CommonModule ,它只导出通用的指令和管道。
当涉及组件,管道和指令时,如果在根模块或任何其他功能模块中导入相同的依赖项,则每个模块都应导入自己的依赖项。 简而言之,即使有多个功能模块,每个功能模块都需要导入CommonModule 。 我们正在使用一种名为exports的新属性。 默认情况下 , declarations数组中定义的每个元素都是私有的 。 我们应该只输出我们应用程序中执行其他任务的其他模块。 在我们的例子中,我们只需要使CreditCardComponent可见,因为它被用在AppComponent的模板中。
app/app.component.ts
...@Component({ ... template: ` ... <app-credit-card></app-credit-card> `})export class AppComponent {}
我们正在将CreditCardMaskPipe保留为私有,因为它仅在CreditCardModule中使用 ,没有被其他模块直接使用。
我们现在可以将此功能模块导入到我们简化的根模块中。
app/app.module.ts
import { NgModule } from '@angular/core';import { BrowserModule } from '@angular/platform-browser';import { CreditCardModule } from '../credit-card/credit-card.module';import { AppComponent } from './app.component';@NgModule({ imports: [ BrowserModule, CreditCardModule ], declarations: [AppComponent], bootstrap: [AppComponent]})export class AppModule { }
到这一步,我们完成了,我们的应用程序如预期的一样。
查看示例
服务和延迟加载模块
这是Angular模块的棘手部分。 除非明确导出组件,管道和指令的范围,否则服务是全局可用的,除非模块被懒加载。
很难理解,我们首先让我们尝试在我们的示例中看到CreditCardService发生了什么。 请注意,该服务不在exports数组中,而是在providers数组中。 通过这种配置,即使在另一个模块中的AppComponent中,我们的服务也将随处可见。 所以,即使使用模块,也没有办法拥有一个“私有”服务,除非这个模块被懒加载。
当模块被懒惰加载时,Angular将创建一个子注入器(它是根模块的根注射器的子代),并且将在那里创建我们的服务实例。
想象一下,我们的CreditCardModule被配置为懒惰加载。 使用我们当前的配置,当应用程序被引导并且我们的根模块加载到内存中时,将会将CreditCardService (单例)的实例添加到根注入器中。 但是,当CreditCardModule在将来某个时候被懒惰加载时,将为该模块创建一个新的CreditCardService 实例的子注入器。 在这一点上,我们有一个分层注入器,具有相同服务的两个实例 ,这通常不是我们想要的。
想想一个执行身份验证的服务的示例。 我们希望在整个应用程序中只有一个单例,不管我们的模块是在bootstrap还是lazy加载的时候加载。 因此,为了使我们的功能模块的服务只添加到根注射器,我们需要使用不同的方法。
credit-card/credit-card.module.ts
import { NgModule, ModuleWithProviders } from '@angular/core';/* ...other imports... */@NgModule({ imports: [CommonModule], declarations: [ CreditCardMaskPipe, CreditCardComponent ], exports: [CreditCardComponent]})export class CreditCardModule { static forRoot(): ModuleWithProviders { return { ngModule: CreditCardModule, providers: [CreditCardService] } }}
不同于以前,我们并没有把我们的服务直接放在NgModule装饰器的providers属性中 。 这一次我们定义了一个名为forRoot的静态方法,通过它定义要导出的模块和服务。
使用这种新语法,我们的根模块略有不同。
app/app.module.ts
/* ...imports... */@NgModule({ imports: [ BrowserModule, CreditCardModule.forRoot() ], declarations: [AppComponent], bootstrap: [AppComponent]})export class AppModule { }
你能发现差异吗? 我们不直接导入CreditCardModule ,而是导入从forRoot方法返回的对象,其中包括CreditCardService 。 虽然这种语法比原始语法更复杂一些,但它将保证我们只有一个CreditCardService实例被添加到根模块中。 当加载CreditCardModule (甚至延迟加载)时,不会将该服务的新实例添加到子注入器。
查看示例
作为经验法则, 在从功能模块导出服务时始终使用forRoot语法 ,除非您有非常特殊的需求,需要在依赖注入树的不同级别进行多个实例。
- (三)创建功能模块
- corethink功能模块探索开发(三)让这个模块可见
- phpcms二次开发_创建功能模块
- phpcms二次开发_创建功能模块
- 一步步实现三方操作功能模块封装(一),三方登录
- 一步步实现三方操作功能模块封装(二),三方分享
- 功能模块
- 基于云信的app聊天(IM)功能模块开发(一)——创建用户
- 网站功能模块的实现:创建model文件夹
- android 功能模块之通讯模块三
- 自定义asterisk功能模块(1)
- 自定义asterisk功能模块(2)
- 笔记——创建一个功能模块的笔记!
- 创建DBLINK(三)
- (三)创建主题
- Android学习之 换肤功能模块的实现<三>
- 学生选课系统(1)-功能模块
- 基础对象创建(三)
- Python基础
- Python3[爬虫实战] 爬虫之scrapy爬取爱上程序网存MongoDB(android模块)
- python 知识点
- PostgreSQL插件开发踩坑之路1
- win32窗口程序-------3、位图及去除背景色
- (三)创建功能模块
- c_day05 联合体-枚举
- IoC之两种获得Bean容器的方法与区别
- 《effective c++》学习笔记(三)
- 获取iOS手机当前最上层的veiwcontroller
- java集合之ArrayList方法的使用实例
- mysql学习笔记
- scrollview 滚动条
- FFT代码实现