1. 核心模块介绍

一个完整的Angular应用主要由六个重要部分构成,分别是:组件、模板、指令、服务、依赖注入和路由。
image.png
与用户交互的是模板视图,模板视图并不是独立的模块,它是组件的组成要素之一。另一要素是组件类,用以维护组件的数据模型及功能逻辑。路由是控制组件的创建和销毁的,从而驱使应用界面跳转切换。指令与模板相互关联,最重要的是增强模板特性、简介扩展了模板语法。服务是封装若干功能逻辑的单元,这个功能逻辑可以通过依赖注入机制引入到组件内部,作为组件功能的扩展。

1.2 组件

Angular框架基与组件设计,应用由一系列大大小小松耦合的组件构成,那组件到底意味着什么?将通过通讯录的例子说明
image.png

  1. @Component({
  2. selector: 'contact',
  3. template: '<div>xxx</div>'
  4. })
  5. export class ContactComponent {
  6. @Input() item: ContactModel;
  7. @Output() update: EventEmitter<ContactModel>;
  8. constructor(){}
  9. }

@Input 和 @Output声明了组件Contact对外暴露的接口,item变量用来接收来自父组件的数据输入,update接口用于向父组件发送数据。那么父组件如何引用子组件并调用这些接口呢?

  1. @Component({
  2. selector: 'contact-list',
  3. template: `<contact [item]="listItem" (update)="doUpdate(newItem)"></contact>`
  4. })
  5. export class ContactListComponent {
  6. listItem: ContactModel[];
  7. constructor(){}
  8. doUpdate(item: ContactModel){}
  9. }

父组件要使用子组件定义标签,需要依赖模块的特性

父组件之间通过类似于HTML属性的方式传递数据,其中[item]称为属性绑定,数据从父组件流向子组件;(update)称为事件绑定。组件类和模板之间的数据交互称为数据绑定
image.png
如下图,这是Angular的数据流动机制,然而流动并不是自发形成的,流动需要一个驱动力,就是Angular的变化检测机制。每次数据变动几乎都能实时的处理并更新对应视图。那么它是如何感知到的呢?它以适当的时机去检测对象的值是否被改动,通常是用户操作事件、setTimeout、XHR回调等这些异步事件触发后。捕获这些异步事件通过Zones库实现的。
image.png
如下图,每个组件背后都维护着一个独立的变化监听器,这个变化监听器记录着所属组件的数据变更状态。由于应用是以组件树的形式组织,每个应用也有着对应的一棵变化检测树。当Zones捕获到某异步事件后,都会通知Angular执行变化检测操作,每次变化监测操作始于根组件并以深度优先的原则向叶子组件遍历执行。
变化检测机制使得开发者不必关心数据何时变动,结合数据绑定实现模板视图实时更新,这就是Angular强大的数据变化监测机制。变化监测机制提供数据自动更新功能,如果需要手动捕获变化事件做一些额外的处理。Angular提供了完善的生命周期钩子给开发者调用。
image.png

1.3 模板

数据绑定是模板的最基本的功能。插值也是很常见的数据绑定用法。插值语法是由一对大括号{{}}组成,插值的变量上下文是组件类本身,插值是一种单向的数据流动—从数据模型到模板视图。数据绑定负责数据的传递和展示,而针对数据的格式化显示,有一种叫管道的功能,用|表示

1.4 指令

指令与模板关系密切,指令可以与DOM进行灵活交互,它或改变样式,改变布局。一般的指令分为两种:结构指令和属性指令。
结构指令能够添加、修改、或删除DOM,从而改变布局,如*ngIf
属性指令用来改变元素的外观和行为,如[ngStyle]

1.5 服务

服务是封装单一功能的单元,类似于工具库,作为组件功能的扩展。它可以是一个简单的字符串,JSON,也可以是一个函数甚至是一个类,几乎所有的对象都可以封装成服务。

1.6 依赖注入

通过依赖注入机制,服务等模块可以被引入任何一个组件,而开发者无需关心这些模块是如何被初始化的。包括该模块本身依赖的其他模块也会被初始化。

  1. @Component({
  2. selector: 'contact-list',
  3. providers: [LoggerService ]
  4. })
  5. export class ContactListComponent {
  6. constructor(private logger: LoggerService){}
  7. doSomething() {
  8. this.logger.info('xxx')
  9. }
  10. }

image.pngimage.png

1.7 路由

  1. [
  2. { path: '', component: ContactListComponent },
  3. { path: 'record', component: RecordListComponent }
  4. ]

image.png
image.png
image.png

2 模块机制

image.png
image.png
image.png
image.png
image.png
image.png