angular2-模块

Angular模块 (NgModule)

Angular 模块是带有 @NgModule 装饰器函数的。 @NgModule接收一个元数据对象,该对象告诉 Angular 如何编译和运行模块代码。 它标记出该模块拥有的组件、指令和管道, 并把它们的一部分公开出去,以便外部组件使用它们。 它可以向应用的依赖注入器中添加服务提供商

模块是组织应用和使用外部库扩展应用的最佳途径。

很多 Angular 库都是模块,例如:FormsModuleHttpModuleRouterModule。 很多第三方库也封装成了 Angular 模块,例如:Material Design、 Ionic、 AngularFire2

模块可能在应用启动时主动加载,也可能由路由器进行异步惰性加载

@NgModule装饰器用来为模块定义元数据。 我们先凭直觉来理解一下元数据

AppModule没有声明过NgIf指令,但该应用仍然能正常编译和运行。为什么这样没问题呢?

Angular 能识别NgIf指令,是因为我们以前导入过它。最初版本的AppModule就导入了BrowserModule

导入BrowserModule会让该模块公开的所有组件、指令和管道在AppModule下的任何组件模板中可用

更准确的说,NgIf是在来自@angular/commonCommonModule中声明的。

CommonModule提供了很多应用程序中常用的指令,包括NgIfNgFor等。

BrowserModule导入了CommonModule并且重新导出了它。 最终的效果是:只要导入BrowserModule就自动获得了CommonModule中的指令。

很多熟悉的 Angular 指令并不属于CommonModule。 例如,NgModelRouterLink分别属于 Angular 的FormsModule模块和RouterModule模块。 在使用那些指令之前,我们也必须导入那些模块

不要把NgModel(或FORMS_DIRECTIVES)加到 AppModule 元数据的declarations数据中!这些指令属于FormsModule`。

组件、指令和管道只能属于一个模块。

永远不要再次声明属于其它模块的类。

如果有两个同名指令,都叫做HighlightDirective,该怎么办呢?

我们只要在 import 时使用as关键字来为第二个指令创建个别名就可以了。

import { HighlightDirective as ContactHighlightDirective } from ‘./contact/highlight.directive‘;

在组件中可以注入服务,但是那样一来,它的作用范围就会局限于该组件及其子组件, 想共享,要添加到AppModule元数据的providers列表中

全应用范围的提供商

ContactService的提供商是全应用范围的,这是因为 Angular 使用该应用的根注入器注册模块的providers

从架构上看,ContactService属于“联系人”这个业务领域。 其它领域中的类并不需要知道ContactService,也不会要求注入它。

我们可能会期待 Angular 提供一种模块范围内的机制来保障此设计。 但它没有。与组件不同,Angular的 模块实例并没有它们自己的注入器,所以它们也没有自己的供应商范围。

Angular是故意这么设计的。 Angular的模块设计,主要目的是扩展应用程序,丰富其模块化能力。

在实践中,服务的范围很少会成为问题。 联系人之外的组件不会意外注入ContactService服务。 要想注入ContactService,你得先导入它的类型。 而只有联系人组件才会导入ContactService类型

特性模块

  • 随着一个个类被加入应用中,根模块AppModule变大了。
  • 我们遇到了指令冲突。 联系人模块的HighlightDirectiveAppModule中声明的HighlightDirective的基础上进行了二次上色。 并且,它染了应用标题文字的颜色,而不仅仅是ContactComponent中的。
  • 该应用在联系人和其它特性区之间缺乏清晰的边界。 这种缺失,导致难以在不同的开发组之间分配职责。
  • 特性模块技术来缓解此问题

特性模块是带有@NgModule装饰器及其元数据的类,就像根模块一样。 特性模块的元数据和根模块的元数据的属性是一样的。

根模块和特性模块还共享着相同的执行环境。 它们共享着同一个依赖注入器,这意味着某个模块中定义的服务在所有模块中也都能用。

import { NgModule }           from ‘@angular/core‘;
import { CommonModule }   from ‘@angular/common‘;
import { FormsModule }        from ‘@angular/forms‘;

import { AwesomePipe }        from ‘./awesome.pipe‘;

import { ContactComponent }   from ‘./contact.component‘;
import { ContactService }     from ‘./contact.service‘;
import { HighlightDirective } from ‘./highlight.directive‘;

@NgModule({
  imports:      [ CommonModule, FormsModule ],
  declarations: [ ContactComponent, HighlightDirective, AwesomePipe ],
  exports:      [ ContactComponent ],
  providers:    [ ContactService ]
})
export class ContactModule { }

  

当前模块不会继承其它模块中对组件、指令或管道的访问权。 AppModule中的 imports 与 ContatModule的 imports 互不相干。 如果ContactComponent要绑定到[(ngModel)],它所在的ContactModule必需导入FormsModule

我们还用CommonModule替换了BrowserModule,其中缘由参见这条常见问题

  我们导出ContactComponent,这样其它模块只要导入了ContactModule,就可以在它们的组件模板中使用ContactComponent了。

声明的所有其它联系人类默认都是私有的。 AwesomePipeHighlightDirective对应用的其它部分是不可见的。 所以HighlightDirective不能把AppComponent的标题文字染色

  

app.module.ts

import { NgModule }           from ‘@angular/core‘;
import { BrowserModule }      from ‘@angular/platform-browser‘;

/* App Root */
import  { AppComponent }       from ‘./app.component‘;
import { HighlightDirective } from ‘./highlight.directive‘;
import { TitleComponent }     from ‘./title.component‘;
import { UserService }        from ‘./user.service‘;

/* Contact Imports */
import { ContactModule }      from ‘./contact/contact.module‘;

@NgModule({
  imports:      [ BrowserModule, ContactModule ],
  declarations: [ AppComponent, HighlightDirective, TitleComponent ],
  providers:    [ UserService ],
  bootstrap:    [ AppComponent ],
})
export class AppModule { }

  

改进之处

修改后的AppModule有一些很棒的特性。

    • 它不会再随着联系人的领域扩张而修改。
    • 只有当添加新模块时才需要修改它。
    • 它也变得简单了:
      • 更少的import语句
      • 不再导入FormsModule
      • 没有与联系人有关的声明
      • 没有ContactService提供商
      • 没有HighlightDirective冲突

路由使用惰性加载语法来告诉路由器要到哪里去找这些模块。

{ path: ‘crisis‘, loadChildren: ‘app/crisis/crisis.module#CrisisModule‘ },
{ path: ‘heroes‘, loadChildren: ‘app/hero/hero.module#HeroModule‘ }

惰性加载模块的位置是字符串而不是类型。 在本应用中,该字符串同时标记出了模块文件和模块,两者用#分隔开。

路由到特性模块

src/app/contact目录中也有一个新文件contact-routing.module.ts。 它定义了我们前面提到过的联系人路由,并提供了ContactRoutingModule,就像这样:

@NgModule({
  imports: [RouterModule.forChild([
    { path: ‘contact‘, component: ContactComponent }
  ])],
  exports: [RouterModule]
})
export class ContactRoutingModule {}

这次我们要把路由列表传给RouterModuleforChild方法  (总是在特性路由模块中调用RouterModule.forChild。)

ContactModule已经做了两个微小但重要的细节改动: imports: [ CommonModule, FormsModule, ContactRoutingModule ],

    • 它从contact-routing.module.ts中导入了ContactRoutingModule对象
    • 它不再导出ContactComponent

现在我们通过路由器导航到 ContactComponent,所以也就没有理由公开它了。它也不再需要选择器 (selector)。 也没有模板会再引用ContactComponent。它从 AppComponent 模板中彻底消失了。

哪些类应该加到declarations中?

只有可声明的类才能加到模块的declarations列表中。

不要声明:

  • 已经在其它模块中声明过的类。无论它来自应用自己的模块(@NgModule)还是第三方模块。
  • 从其它模块中导入的指令。例如,不要声明来自@angular/forms的FORMS_DIRECTIVES。
  • 模块类
  • 服务类
  • 非Angular的类和对象,比如:字符串、数字、函数、实体模型、配置、业务逻辑和辅助类。
时间: 2024-10-09 14:26:11

angular2-模块的相关文章

Angular2 NgModule

1. 说明 典型的模块是一个内聚的代码块,用来实现某种单一的功能.Angular2应用程序本质上是有一系列模块组成的,而且Angular 本身就是一组模块库.模块主要是导出一些东西——类,函数,值,供其它模块导入,然后使用这个类,函数或者值.Angular2 应用是模块化的,并且 Angular2 有自己的模块系统,它被称为 Angular2 模块 或 NgModules. NgModules是带有 @NgModule 装饰器函数的 类 . @NgModule 接收一个元数据对象,该对象告诉 A

初识Angular2

初识Angular2 写一个Angular2的Hello World应用相当简单,分三步走: 1. 引入Angular2预定义类型 import {Component,View,bootstrap} from "angular2/angular2"; import是ES6的关键字,用来从模块中引入类型定义.在这里,我们从angular2模块库中引入了三个类型: Component类.View类和bootstrap函数. 2. 实现一个Angular2组件 实现一个Angular2组件也

Angular2入门(二)

初识Angular2 写一个Angular2的Hello World应用相当简单,分三步走: 1. 引入Angular2预定义类型 1 import {Component,View,bootstrap} from "angular2/angular2"; import是ES6的关键字,用来从模块中引入类型定义.在这里,我们从angular2模块库中引入了三个类型: Component类.View类和bootstrap函数. 2. 实现一个Angular2组件 实现一个Angular2组

AngularJS2.0 教程系列(一)

Why Angular2 Angular1.x显然非常成功,那么,为什么要剧烈地转向Angular2? 性能的限制 AngularJS当初是提供给设计人员用来快速构建HTML表单的一个内部工具.随着时间的推移,各种特性 被加入进去以适应不同场景下的应用开发.然而由于最初的架构限制(比如绑定和模板机制),性能的 提升已经非常困难了. 快速变化的WEB 在语言方面,ECMAScript6的标准已经完成,这意味着浏览器将很快支持例如模块.类.lambda表达式. generator等新的特性,而这些特

Angular 2 入门二

ES6工具链 原文:汇智网 要让Angular2应用跑起来不是件轻松的事,因为它用了太多还不被当前主流浏览器支持 的技术.所以,我们需要一个工具链: Angular2是面向未来的科技,要求浏览器支持ES6+,我们现在要尝试的话,需要加一些 垫片来抹平当前浏览器与ES6的差异: systemjs - 通用模块加载器,支持AMD.CommonJS.ES6等各种格式的JS模块加载 es6-module-loader - ES6模块加载器,systemjs会自动加载这个模块 traceur - ES6转

赵教授的课程

课程名称 课程内容 课程时间 课程时长 需提前学习的知识 JavaScript基础课程1 js 语法,变量,对象,函数,作用域 4/12/2018 1 javascript 基础知识 JavaScript基础课程2 js 正则表达式, 原型设计,严格模式,等等 4/13/2018 1 javascript 基础知识 jQuery基础课程1 语法,选择器,事件 4/26/2018 1 jquery基础知识 jQuery基础课程2 函数,ajax,等等 4/27/2018 1 jquery基础知识

Angular2 小贴士 NgModule 模块

angular2 具有了模块的概念,响应了后台程序的号召,高内聚 低耦合.模块就是用来进行封装,进行高内聚  低耦合的功能. 其实各人认为ng2 的模块和.net的工程类似,如果要使用模块中定义的功能,第一步就是必须要引用它,ng2 中叫import 导入. 那么我们看模块是否有层级概念呢,至少目前来看,模块都是平级的,没有主子之分. 如何定义模块呢? 1 import { NgModule } from '@angular/core'; 2 import { BrowserModule } f

在Angular2 如何通过npm安装lodash模块

为了更好地在angular2 里面对JSON 数据进行处理.我们可以添加lodash模块来更加简便我们的工作 这里我简单介绍一下如何安装lodash 到angular2 前提: 01 这里默认已经安装了node.js. 02 默认typescript 版本>2.0 eg "typescript": "^2.0.3", 03 默认已经创建angular2 npm 架构的项目 1 通过npm 安装lodash.这里可以通过以下命令行来安装 $ npm i -g n

Angular2的模块架构浅谈

一.根模块.子模块与惰性加载 先说根模块.一个ng2应用至少要有一个根模块,包含ng2自带的BrowserModule,并声明为引导模块,在应用启动时将从此模块展开.随着应用的扩大,所有的事情都在一个模块中完成难免会变乱(某种程度上看ng1应用就是这么做的,并且细分了控制器来拆分应用,这其实浪费了最顶层模块的意义),所以自然而然能想到,可以将系统分为多个模块,每个模块都只做各自的事情而互不干扰,所以进一步的思路就是,用来根模块来引导程序并管理所有子模块(通过路由定向以及为它们提供全局配置与服务实

Angular2入门:TypeScript的模块

一.export 二.import 三.模块的默认导出 原文地址:https://www.cnblogs.com/lexiaofei/p/9215424.html