angular架构

Angular 是一个用 HTML 和 TypeScript 构建客户端应用的平台与框架。 Angular 本身使用 TypeScript
写成的。它将核心功能和可选功能作为一组 TypeScript 库进行实现,你可以把它们导入你的应用中。

一:模块

NgModule 为一个组件集声明了编译的上下文环境,NgModule 可以将其组件和一组相关代码(如服务)关联起来,形成功能单元

每个 Angular 应用都有一个根模块,通常命名为 AppModule。根模块提供了用来启动应用的引导机制。
一个应用通常会包含很多功能模块。

像 JavaScript 模块一样,NgModule 也可以从其它 NgModule 中导入功能,并允许导出它们自己的功能供其它
NgModule 使用。 比如,要在你的应用中使用路由器(Router)服务,就要导入 Router 这个 NgModule。

export class AppModule { }   //导出

import { AppModule } from './app/app.module';   //导入

这项技术还能让你获得按需加载模块的优点,以尽可能减小启动时需要加载的代码体积。

NgModule 是一个带有 @NgModule 装饰器的类,@NgModule 装饰器是一个函数,它接受一个元数据对象,该对象的属性用来描述这个模块

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

解释

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

exports(导出表) —— 那些能在其它模块的组件模板中使用的可声明对象的子集,为空是因为根模块没有任何理由导出任何东西,因为其它模块永远不需要导入根模块。

imports(导入表) —— 导入其他模块

providers —— 定义服务,这些服务能被本应用中的任何部分使用。(你也可以在组件级别指定服务提供商,这通常是首选方式。在这里面定义之后在组件里面只需要注入不需要在组件内定义了)

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

NgModule与组件的关系:

根模块总会有一个根组件,并在引导期间创建它,

比如前面介绍的元数据bootstrap中定义的AppComponent就是 AppModule的根组件

任何模块都能包含任意数量的组件,这些组件可以通过路由器加载,也可以通过模板创建。属于这个 NgModule
的组件会共享这个模块提供的同一个编译上下文环境。

angular自带的库

Angular 自带了一组 JavaScript 模块,你可以把它们看成库模块。每个 Angular 库的名称都带有 @angular
前缀。 使用 npm install 包管理器安装它们,并使用 JavaScript 的 import 语句导入其中的各个部分。

import { Component } from '@angular/core';   //从 @angular/core 库中导入 Component 装饰器
import { BrowserModule } from '@angular/platform-browser';  //从 Angular 库中导入 Angular 模块:这个代码从 platform-browser 库中导入了 BrowserModule 模块

NgModule 和 JavaScript 的模块

这两种模块系统不同但互补。你可以同时使用 Angular 和 JavaScript 的这两种模块系统。 虽然这两种模块系统容易混淆(它们共享了同样的词汇 import 和export

二:组件

下面的例子中就是 HeroListComponent 的基础元数据:

@Component({
  selector:    'app-hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

组件控制视图上的一小片区域,视图都是由一个个组件所组成和控制的

组件通过一些由属性和方法组成的 API 与视图交互。

export class HeroListComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(private service: HeroService) { }

  ngOnInit() {
    this.heroes = this.service.getHeroes();
  }

  selectHero(hero: Hero) { this.selectedHero = hero; }
}

比如上面的组件就由heroes、selectedHero属性以及 selectHero()方法与视图进行数据交互的

每个 Angular 应用都至少有一个组件,也就是根组件—AppComponent,每个组件都会定义一个类,其中包含应用的数据和逻辑

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

模板与视图

模板就是一种 HTML,它会告诉 Angular 如何渲染该组件

模板很像标准的 HTML,但是它还包含 Angular 的模板语法,你的模板可以使用数据绑定加粗样式来协调应用和 DOM
中的数据,使用
管道在显示出来之前对其进行转换,使用指令来把程序逻辑应用到要显示的内容上。

<h2>Hero List</h2>

<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>

<app-hero-detail *ngIf="selectedHero" [hero]="selectedHero"></app-hero-detail>

上面的例子使用了典型的 HTML 元素,比如 <h2> 和 <p>,还包括一些 Angular 的模板语法元素,如 *ngFor(指令),{{hero.name}}(数据绑定),click(数据绑定)、[hero] (数据绑定)和 <app-hero-detail>(组件的子组件)

1:数据绑定

Angular 支持双向数据绑定

数据绑定标记有四种形式。每种形式都有一个方向 —— 从组件到 DOM、从 DOM 到组件或双向

<li>{{hero.name}}</li>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<li (click)="selectHero(hero)"></li>
<input [(ngModel)]="hero.name">


分析:
1:{{}}:插值表达式   从组件---DOM
2:[hero] = ''selectedHero'' 属性绑定,把父组件 HeroListComponent 的 selectedHero 的值传到子组件 HeroDetailComponent 的 hero 属性中。从组件---DOM
3:(click)=''selectHero(hero)''事件绑定   从DOM---组件
 4:[(ngModel)] = ''hero.name''  双向绑定  从DOM<>组件

在双向绑定中,数据属性值通过属性绑定从组件流到输入框用户的修改通过事件绑定流回组件,把属性值设置为最新的值。

数据绑定在模板及其组件之间的通讯中扮演了非常重要的角色,它对于父组件和子组件之间的通讯也同样重要。

2:管道

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

Angular 自带了很多管道,比如 date 管道和 currency 管道,你也可以自己定义一些新管道。

语法:{{value_name| pipe_name}}

3:指令

Angular 的模板是动态的。当 Angular 渲染模板的时候,会根据指令给出的指示对 DOM 进行转换。 指令就是一个带有
@Directive 装饰器的类。

组件从技术角度上说就是一个指令,除组件外,还有两种指令:结构型指令和属性型指令

<1结构型指令

结构型指令通过添加、移除或替换 DOM 元素来修改布局

<li *ngFor="let hero of heroes"></li>
<app-hero-detail *ngIf="selectedHero"></app-hero-detail>

<2属性型指令

属性型指令会修改现有元素的外观或行为。 在模板中,它们看起来就像普通的 HTML 属性一样,因此得名“属性型指令”

ngModel 指令就是属性型指令的一个例子,它实现了双向数据绑定。 ngModel 修改现有元素(一般是 )的行为:设置其显示属性值,并响应 change 事件。Angular 还有很多预定义指令,它们或者修改布局结构(比如 ngSwitch),或者修改 DOM 元素和组件的某些方面(比如 ngStyle 和 ngClass)。

<input [(ngModel)]="hero.name">

三:服务与依赖注入

<1:服务

比如你写了一个公共的方法,这个方法将在很多组件中用到,你就可以把这个公共方法写进一个服务里面,到时候只需要在不同组件引入这个服务就好,我理解的服务就是服务组件的类,Angular 把组件和服务区分开,以提高模块性和复用性。

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

服务类的定义通常紧跟在 “@Injectable” 装饰器之后

该装饰器提供的元数据可以让你的服务作为依赖被注入到客户组件中。

下面是一个服务类的范例,用于把日志记录到浏览器的控制台:

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

服务也可以依赖其它服务

<2:依赖注入(DI)

你可以把一个服务注入到组件中,让组件类得以访问该服务类,在 Angular 中,要把一个类定义为服务,就要用 @Injectable
装饰器来提供元数据,以便让 Angular 可以把它作为依赖注入到组件中

constructor(private service: HeroService) { }

对于任何服务,你必须至少注册一个提供商,你也可以为特定的模块或组件注册提供商。要注册提供商,就要在服务的 @Injectable 装饰器中提供它的元数据providedIn,或者在@NgModule 或 @Component 的元数据providers中。

@Injectable({
  providedIn: 'root',  
})

当你在组件级注册提供商时,你会为该组件的每一个新实例提供该服务的一个新实例。 要在组件级注册,就要在 @Component 元数据的
providers 属性中注册服务提供商。

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers:[]
})

当你使用特定的 NgModule 注册提供商时,该服务的同一个实例将会对该 NgModule 中的所有组件可用。要想在这一层注册,请用
@NgModule 装饰器中的 providers 属性

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})

五:路由

它的工作模型基于人们熟知的浏览器导航约定

不过路由器会把类似 URL 的路径映射到视图而不是页面,当用户执行一个动作时(比如点击链接),本应该在浏览器中加载一个新页面,但是路由器拦截了浏览器的这个行为,并显示或隐藏一个视图层次结构。

如果路由器认为当前的应用状态需要某些特定的功能,而定义此功能的模块尚未加载,路由器就会按需惰性加载此模块。

这五个概念会有详细的教程。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章