Angular 源码及架构分析

时间:2024-03-23 09:32:12

Angular 源码及架构分析

 

Angular 的基本构造块是 NgModule

Angular 源码及架构分析


        至少会有一个用于引导应用的根模块(AppModule),和很多特性模块,提供上下文环境

组件定义视图
组件使用服务
宿主视图、内嵌视图、@angular 前缀

模块
模块化系统,称作 NgModule,一个容器,用于存放一些内聚的代码块

@NgModule 装饰器

declarations(可声明对象表) —— 那些属于本 NgModule 的组件、指令、管道。

exports(导出表) —— 那些能在其它模块的组件模板中使用的可声明对象的子集。

imports(导入表) —— 那些导出了本模块中的组件模板所需的类的其它模块。

providers —— 本模块向全局服务中贡献的那些服务的创建器。 。(你也可以在组件级别指定服务提供商,这通常是首选方式。)

bootstrap —— 应用的主视图,称为根组件。它是应用中所有其它视图的宿主。只有根模块才应该设置这个 bootstrap 属性。

组件
@Component 装饰器表明紧随它的那个类是一个组件,并提供模板和该组件专属的元数据。

带有导航链接的应用根组件。

英雄列表。

英雄编辑器。

元数据
如何在 HTML 中引用该组件,以及该组件需要哪些服务等等。

selector:是一个 CSS 选择器,它会告诉 Angular,一旦在模板 HTML 中找到了这个选择器对应的标签,就创建并插入该组件的一个实例。 比如,如果应用的 HTML 中包含 <app-hero-list></app-hero-list>,Angular 就会在这些标签中插入一个 HeroListComponent 实例的视图。

templateUrl:该组件的 HTML 模板文件相对于这个组件文件的地址。 另外,你还可以用 template 属性的值来提供内联的 HTML 模板。 这个模板定义了该组件的宿主视图。

providers 是当前组件所需的依赖注入提供商的一个数组。在这个例子中,它告诉 Angular,该组件的构造函数需要一个 HeroService 实例,以获取要显示的英雄列表。

模板(HTML)、指令和数据绑定
事件绑定让你的应用可以通过更新应用的数据来响应目标环境下的用户输入。

属性绑定让你将从应用数据中计算出来的值插入到 HTML 中。

数据绑定:从组件到 DOM、从 DOM 到组件或双向。

模板是包在 ECMAScript 2015 反引号 (`) 中的一个多行字符串。 反引号 (`) — 注意,不是单引号 (') — 允许把一个字符串写在多行上, 使 HTML 模板更容易阅读。

管道
@Pipe 装饰器定义一个转换函数,用来把输入值转换成供视图显示用的输出值。

比如 date 管道和 currency 管道

要在 HTML 模板中指定值的转换方式,请使用 管道操作符 (|)。

{{interpolated_value | pipe_name}}

指令
面向模板@Directive 装饰器和@Component 装饰器

结构型指令和属性型指令

结构型指令

通过添加、移除或替换 DOM 元素来修改布局。

<li *ngFor="let hero of heroes"></li>
<app-hero-detail *ngIf="selectedHero"></app-hero-detail>
*ngFor 是一个迭代器,它要求 Angular 为 heroes 列表中的每个 <li> 渲染出一个 <li>。
*ngIf 是个条件语句,只有当选中的英雄存在时,它才会包含 HeroDetail 组件。

属性型指令

修改现有元素的外观或行为

双向数据绑定

ngModel 修改现有元素(一般是 <input>)的行为:设置其显示属性值,并响应 change 事件。

预定义指令

Service与依赖注入
对于与特定视图无关并希望跨组件共享的数据或逻辑,可以创建服务类。

@Injectable” 装饰器

写在constructor

constructor(private logger:LoggerService){}
当用户在应用中穿行时,Angular 就会创建、更新、销毁一些组件。 你的应用可以通过一些可选的生命周期钩子(比如ngOnInit())来在每个特定的时机采取行动。 

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}
路由
在应用的各个不同状态和视图层次结构之间导航时要使用的路径

在地址栏输入 URL,浏览器就会导航到相应的页面。

在页面中点击链接,浏览器就会导航到一个新页面。

点击浏览器的前进和后退按钮,浏览器就会在你的浏览历史中向前或向后导航。

惰性加载模块

路由器会根据你应用中的导航规则和数据状态来拦截 URL

为数据创建一个类
用构造函数的参数直接定义属性。

export class Hero {
  constructor(
    public id: number,
    public name: string) { }
}
使用 Hero 类
heroes = [
  new Hero(1, 'Windstorm'),
  new Hero(13, 'Bombasto'),
  new Hero(15, 'Magneta'),
  new Hero(20, 'Tornado')
];
myHero = this.heroes[0];
 

总结
组件和模板共同定义了 Angular 的视图。

组件类上的装饰器为其添加了元数据,其中包括指向相关模板的指针。

组件模板中的指令和绑定标记会根据程序数据和程序逻辑修改这些视图。

依赖注入器会为组件提供一些服务,比如路由器服务就能让你定义如何在视图之间导航。

响应式编程工具

生命周期钩子:通过实现生命周期钩子接口,可以窃听组件生命周期中的一些关键时刻 —— 从创建到销毁。

可观察对象(Observable)和事件处理:如何在组件和服务中使用可观察对象来发布和订阅任意类型的消息,比如用户交互事件和异步操作结果。

 

 

 

客户端与服务器的交互工具

HTTP:用 HTTP 客户端与服务器通讯,以获取数据、保存数据或执行服务端动作。

服务端渲染:Angular Universal 会通过服务端渲染(SSR)技术在服务器上生成静态的应用页面。 这让你可以在服务器上运行 Angular 应用,以提升性能并在手机或低功耗设备上快速显示首屏,并为 Web 爬虫提供帮助(SEO)。

Service Worker:Service Worker 是一个运行在浏览器中并为应用管理缓存的脚本。 Service Worker 的功能类似于网络代理。它们会拦截发出的 HTTP 请求,如果存在已缓存的响应,则直接返回它。通过使用 Service Worker 来减轻对网络的依赖,你可以显著提升用户体验。
 

 

 

Angular的每一个组件都存在一个生命周期,从创建,变更到销毁,就是一个组件的完整的生命周期。Angular提供组件生命周期钩子,把组件在生命周期种的这些关键时刻暴露出来,赋予在这些关键结点和组件进行交互的能力。

Angular的生命周期钩子有八种,按照生命周期的执行顺序如下

1. ngOnChanges

时机:当被绑定的输入属性(@input)的值发生变化时调用,首次调用一定会发生在 ngOnInit之前;该回调方法会收到一个包含当前值和原值的changes对象。在有输入属性的情况下才会调用,该方法接受当前和上一属性值的SimpleChanges对象。如果有输入属性,会在ngOnInit之前调用。

接口:OnChanges;

适用范围: 指令和组件种;

 

2.ngOnInit

时机:在第一轮 ngOnChanges 完成之后调用。 ( 也就是说当每个输入属性(@input)的值都触发了一次ngOnChanges 之后才会调用ngOnInit ,此时所有的输入属性都已经有了正确的初始绑定值 );在组件初始化的时候调用,只调用一次,在第一次调用ngOnChanges之后调用

接口: OnInit

适用范围: 指令和组件种

 

3.ngDoCheck 

时机:在每个 Angular 变更检测周期中调用;用来检测所有变化(无论是Angular本身能检测还是无法检测的),并作出相应行动。在每次执行“变更检测”时被调用。在组件定义的属性或方法变更时调用(用于脏值之检测,非常耗性能,因为会把所有的属性和方法都检测一遍)

接口: DoCheck;

适用范围: 指令和组件中

 

4.ngAfterContentInit 

时机:当把内容投影进组件之后调用;在组件内容初始化之后调用,在第一次ngDoCheck之后调用,只调用一次

接口:AfterContentInit 

适用范围: 组件中

5.ngAfterContentChecked

时机:每次完成被投影组件内容的变更检测之后调用;在组件每次检查内容放生变更时调用。在ngAfterContentInit和每次ngDoCheck之后调用

接口:AfterContentChecked

适用范围:组件中

 

6.ngAfterViewInit

时机:初始化完组件视图及其子视图之后调用;在组件相应的视图初始化之后调用,第一次ngAfterContentChecked之后调用,只调用一次

接口:AfterViewInit

适用范围:组件中

 

7.ngAfterViewChecked

时机:每次做完组件视图和子视图的变更检测之后调用;在组件每次检查视图发生变更时调用。ngAfterViewInit和每次ngAfterContentChecked之后调用。

接口:AfterViewChecked;

适用范围:组件中

 

8.ngOnDestroy

时机:当 Angular 每次销毁指令 / 组件之前调用;在Angular销毁指令或组件之前做一些清理工作,比如退订可观察对象和移除事件处理器,以免导致内存泄漏。

接口:OnDestroy

适用范围:指令和组件中