翻译 Angular2 文档指南中的 [架构概述] 一节
话题
这是Angular2核心文档指南的翻译。
-
- DOCUMENTATION OVERVIEW – ドキュメント概要 –
-
- ARCHITECTURE OVERVIEW – 構文概要 –
-
- DISPLAYING DATA – データ表示 –
-
- USER INPUT – ユーザー入力 –
-
- FORMS – フォーム –
-
- DEPENDENCY INJECTION – 依存性注入 –
- STYLE GUIDE - スタイルガイド –
请注意,未在此处列出的项目,请直接参考Angular 2核心文档指南。
请注意2)这个翻译是基于2016年10月4日的版本。翻译者在TOEIC考试中取得了大约700分的英语水平,所以英文翻译可能存在错误的可能性。此外,还有一些地方是相当意译的。如果有地方超出了意译的范围,出现了错误翻译,请您指出。
建筑概览 – 架构概述 –
Angular应用程序的基础构成要素
Angular是一个用于构建客户端应用程序的框架,它可以使用HTML和JavaScript,或者JavaScript编译语言(如Dart或TypeScript)。
Angular 包含一些核心库和可选库。构建 Angular 应用时,首先需要创建使用 Angular 标记的 HTML 模板,并编写管理这些模板的组件类。然后加入应用逻辑到服务中,并将组件和服务添加到模块中。
当您启动根模块并启动应用程序后,它将接管您在浏览器中保持的状态,以响应您发出的用户交互。
当然,Angular仍然有许多需要掌握的内容。让我们从现在开始,在这个页面上详细学习它们。首先,我们将展示整体概览。

这个结构图由 Angular 应用程序的八个主要组成部分组成。
-
- Modules – モジュール –
-
- Components – コンポーネント –
-
- Templates – テンプレート-
-
- Metadata – メタデータ-
-
- Data binding – データバインディング-
-
- Directives – ディレクティブ-
-
- Services – サービス-
- Dependency injection – 依存性注入-
请以你自己的方式学习这些构成要素。
在此页面上所引用的代码可以在实时示例中使用。
模块 – 模块 –

Angular应用程序是由模块(组装)组成的,并且Angular本身也是一个称为Angular模块或NgModules的模块化系统。
由于Angular模块是一个相当大的主题,所以在本页面中只介绍了模块的基本概念。
请在Angular模块页面中进一步了解。
所有的Angular应用程序至少都有一个被习惯性地命名为AppModule的根模块。
在小型应用程序中,根模块是应用程序内唯一的模块,但在许多应用程序中,还有许多功能模块。这些功能模块分别是应用程序领域、工作流程或与性能密切相关的功能代码的集合体。
无论是根模块还是功能模块,Angular模块都是一个带有@NgModule装饰器的类。
装饰器是一种用于修饰 JavaScript 类的功能。Angular 提供了多个装饰器,它们会将元数据附加到类上,以便了解该类的含义和功能。请在本网站上学习有关装饰器的内容。
@NgModule是一个装饰器,它是一个具有解释该模块的属性的唯一元数据对象。以下是最重要的属性:
declarations – このモジュールに属するビュークラスです。Angularはcomponents、directives、pipesという3種類のビュークラスを持ちます。
exports – ほかのモジュールにあるコンポーネントテンプレートの中で、閲覧および使用を可能にするdeclarationsのサブセットです。
imports – exportされたクラスを持ち、このモジュール内で宣言されたコンポーネントテンプレートに必要とされるほかのモジュールです。
providers – オリジナルで作成したサービスを、このモジュールのグローバルコレクションサービスに追加します。これにより、そのサービスはアプリ内のどこからでもアクセスできるようになります。
bootstrap – ルートコンポーネントと呼ばれるメインアプリケーションビューが、他のすべてのアプリケーションビューの基礎となります。bootstrapプロパティは、ルートモジュールでのみ設定するようにしてください。
以下是一个简单的路由模块示例。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
AppComponent的导出只是为了展示导出的方法而设立的例子,所以实际上并不需要在这个例子中使用。
由于其他组件不需要导入根模块,所以根模块没有什么需要导出的东西。
请启动路由模块并尝试运行应用程序。如果要在开发中启动AppModule,请将main.ts文件配置如下也许会有帮助。
COPY CODE
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Angular模块与JavaScript模块
Angular模块是一个具有@NgModule装饰器的类,它是Angular的基础功能。
此外,JavaScript具有管理JavaScript对象集合的模块机制,这与Angular的模块系统完全不同,也没有关联性。
JavaScript的每个文件都作为一个模块,所有的对象都在该模块的文件中进行定义。JavaScript模块使用export关键字声明对象为公共对象,并使用import语句访问其他模块中声明为公共对象的对象。
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
export class AppModule { }
请在此网站上学习JavaScript模块的机制。
在Angular中有两个不同但互补的模块系统。当您创建应用程序时,请使用它们。
Angular库

Angular是一个包含JavaScript模块的集合,并将它们作为库模块进行处理。
Angular库的名称以前缀@angular开头。
Angular的库可以通过npm包管理器进行安装,并通过JavaScript的import语句进行导入。
作为示例,让我们尝试从 @angular/core 导入 Angular 的 Component 装饰器。
import { Component } from '@angular/core';
此外,您还可以使用JavaScript中的import语句,从Angular库中导入Angular模块。
import { BrowserModule } from '@angular/platform-browser';
在上述简易路由模块的例子中,应用程序模块需要从BrowserModule获取数据。为了访问该数据,在@NgModule元数据的import中添加BrowserModule,如下所示。
imports: [ BrowserModule ],
通过这种方式,可以同时使用Angular和JavaScript的模块系统。
然而,由于它们共享了相同的词汇“进口”和“出口”,所以容易给这两个系统带来混淆。
请努力理解,这需要时间和经验。
请深入学习Angular模块的页面。
构成组件 – 组件 –

组件负责管理被称为视图的屏幕部分。
例如,以下的屏幕是由组件来控制的。
-
- ナビゲーションリンクを伴うアプリのルート画面
-
- heroesのリスト
- heroの編集
必须将包含对视图支持内容的组件的应用逻辑定义为类。该类将对API的属性和方法产生影响。
例如,HeroListComponent具有一个heroes属性,当从服务中请求时,该属性会返回heroes数组。此外,HeroListComponent还具有一个selectHero()方法,当用户从heroList中选择一个hero并点击时,会设置selectedHero属性。
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; }
}
Angular根据应用程序中用户的动作,创建、更新和销毁组件。可以使用任何生命周期钩子,例如在上述声明的ngOnInit()函数中,根据不同的生命周期阶段执行相应的操作。
模板 – 模版-

当定义组件的视图时,还需要定义相应的模板。
模板用于以HTML格式告诉Angular如何渲染组件。
除了一些细微的差异,模板看起来与普通的HTML相同。
在HeroListComponent中,模板如下所示。
<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>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>
在此模板中,我们使用了一些典型的HTML元素,例如
和
,但也包含了一些差异。像*ngFor、{{hero.name}}、(click)、[hero]、这样的代码,是使用了Angular的模板语法。
在这个模板的最后一行,我们使用自定义元素标签来显示一个新的组件HeroDetailComponent。
HeroDetailComponent和之前提到的HeroListComponent是不同的组件。HeroDetailComponent(不提供代码)显示了用户从HeroListComponent中选择的特定hero的信息。HeroDetailComponent是HeroListComponent的子组件。

请注意与原生HTML元素非常相容的事实。自定义组件与原生HTML在同一布局中无缝混合。
元数据

元数据显示了在Angular中处理类的方法。
当回顾HeroListComponent的代码时,您将发现它只是一个简单的类。它既不是框架的证据,也没有任何与“ Angular”相关的描述。
从事实来看,HeroListComponent只是一个普通的类。除非通过Angular告知它是一个组件,否则它并不具备组件的特性。
为了告诉Angular,HeroListComponent是一个组件,需要在类上附加元数据。
在TypeScript中,我们可以使用装饰器给代码添加元数据。HeroListComponent的元数据如下所示。
@Component({
moduleId: module.id,
selector: 'hero-list',
templateUrl: 'hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}
在这里,@Component装饰器将其下方的类立即确定为组件类。
@Component 装饰器是 Angular 需要的一个必要配置对象,用于创建和显示组件和视图的必要信息。
@Component可用的配置选项非常有限,如下所示。
moduleId: templateUrlのようなモジュールに関連するURLのために、ベースとなるアドレス(module.id)のソースを設定します。
selector: コンポーネントのインスタンスを作成し、挿入することをAngularに伝えるCSSセレクタです。親となるHTMLの中でタグを見つけるためには、ここで明示しておく必要があります。たとえば、もしアプリ内にあるHTMLがを含んでいた場合、Angularはこのタグの間にHeroListComponentのビューインスタンスを挿入します。
templateUrl: 上記のような、コンポーネントのHTMLテンプレートを紐づける、モジュールに関連するアドレスです。
providers: コンポーネントが必要とするサービスを使うために、Dependency Injectionプロバイダを列挙します。これはコンポーネントのコンストラクタがHeroServiceを要求することをAngularに伝える方法の1つであり、それによってheroesを表示するためのリストを取得できます。

@Component中的元数据会向Angular传达组件明确声明的重要组成部分可以在哪里获取。
模板、元数据和组件相互关联以渲染视图。
(Note: Translation may vary based on context)
为了确定Angular的行为,请使用其他元数据装饰器来采用相同的形式。
@Injectable、@Input、@Output是常用的装饰器,但不是非常多。
总结来看,为了让Angular发挥作用,您需要在您编写的代码中添加元数据。
数据绑定
如果没有框架的话,你需要确保将数据值注入到HTML中,并将用户操作转换为动作和值的更新控制。手动编写类似push和pull的逻辑非常枯燥易错,无论你是多么熟练的jQuery程序员,读起来都会是一场噩梦。

Angular支持数据绑定机制,可以将组件部分和模板部分同步。为了告诉Angular它们如何相互连接,需要在模板HTML中添加绑定标记。
根据图示,数据绑定的语法有四种表示方法。每种方法都具有”DOM到数据”、”数据到DOM”、”双向”的方向性。
在HeroListComponent的模板示例中,使用了三种语法。
<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>
{{hero.name}}は、
- タグの中で、コンポーネントにあるhero.nameプロパティの値と置き換えて表示されます。[hero] プロパティバインディングは、親であるHeroListComponentから、子であるHeroDetailComponentのheroプロパティにselectedHeroの値を渡します。
(click)イベントバインディングは、ユーザーがheroの名前をクリックしたときに、コンポーネントにあるselectHeroメソッドを呼び出します。
在使用ngModel指令时,双向绑定是将属性和事件绑定在单一表示法中的重要第四种表示法。
HeroDetailComponent模板中存在以下示例。
<input [(ngModel)]="hero.name">
在双向绑定中,通过属性绑定,将组件中的数据属性值传递给输入框。同时,当用户更改值时,通过事件绑定将该信息传递给组件,并将属性重新设置为最新值。
Angular会通过应用程序组件树,从根组件到所有子组件,在每个JavaScript事件循环中处理所有数据绑定。

数据绑定在模板和组件相互交互时扮演了重要的角色。

数据绑定在父子组件之间进行互动时也很重要。
指令 – 指导性文件-

Angular模板是动态的。当Angular渲染模板时,根据指令提供的指示,会改变DOM。
指令是带有指令元数据的类。在TypeScript中,请使用@Directive装饰器将元数据附加到类上。
组件是具有模板的指令。@Component装饰器实际上是通过使用与模板相关的功能来扩展@Directive装饰器。
组件在技术上是指令,但它是Angular应用程序的特征性和核心功能之一,因此在这个架构概述中,我们区分对待指令和组件。
除此之外,还存在着两种不同的指令:结构指令和属性指令。
这些指令通常用作标签元素的属性,有时也用作标签名称,但主要用于赋值和绑定。
构造指令通过添加、删除、交换DOM元素来改变布局。
在以下模板示例中,使用了两个内置结构指令。
<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>
*ngForはheroesリストをまわして、heroごとに1つの
- を出力するようAngularに伝えています。*ngIfは、選択されたheroが存在している場合のみ、HeroDetailコンポーネントを表示させます。
属性指令会改变显示元素的行为或表达方式。在模板中,它们类似于常规的HTML属性,因此被称为属性指令。
ngModel是一种使用双向绑定的方式来实现的属性指令,它是属性指令的一个例子。通过设置显示值的属性或更改事件,ngModel指示并改变显示元素(典型的例子是)的行为。
<input [(ngModel)]="hero.name">
在Angular中,并不是有很多,但仍然有一些可用于修改布局结构的指令,例如ngSwitch,以及用于修改DOM元素或组件外观的指令,例如ngStyle和ngClass。
当然,您也可以编写自己的指令。像HeroListComponent这样的组件就是自定义指令的一个示例。
服务

该服务涵盖了广泛的类别,并覆盖了应用程序所需的所有值、函数和功能。
任何东西都可以成为服务。服务通常是规模较小且具有常见用途的类别,但最好是目标明确且精心策划的。
服务的例子
-
- ログサービス
-
- データサービス
-
- バグ報告
-
- 税計算
- アプリケーション環境設定
在Angular的服务中,没有什么特别的事情。
服务没有被定义,服务的原型类也没有被确定,安装的位置也没有确定。
然而,服务是每个Angular应用程序的基础。换句话说,组件是服务的专业用户。
在这里,我将展示一个服务类的例子,该例子可以在浏览器控制台上显示日志。
export class Logger {
log(msg: any) { console.log(msg); }
error(msg: any) { console.error(msg); }
warn(msg: any) { console.warn(msg); }
}
接下来,我将展示一个在启动时使用Promise访问heros并返回HeroService的例子。HeroService依赖于Logger service和另一个名为BackendService的服务,该服务用于与服务器进行交互,这是一项不太想做的工作。
export class HeroService {
private heroes: Hero[] = [];
constructor(
private backend: BackendService,
private logger: Logger) { }
getHeroes() {
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
this.logger.log(`Fetched ${heroes.length} heroes.`);
this.heroes.push(...heroes); // fill cache
});
return this.heroes;
}
}
无论服务在哪里都可以。
组件类的代码应该尽可能简洁。在组件类中,不要直接访问服务器数据、验证用户输入或将日志直接输出到控制台,而是应该将这些工作交给服务来处理。
组件的工作不仅仅是让用户体验成为可能,还要负责调整视图(由模板渲染)和应用程序逻辑(通常用作模型概念)之间的配合。
组件通常具有用于数据绑定的属性和方法,通过这些可以将所有重要事务委托给服务。
Angular没有强制这样的原则。即使你写了一个像”万能水槽”那样的3000行组件,也不会有任何指责。
Angular通过将应用程序逻辑整合为服务,使其更易于遵循上述原则,并使用依赖注入来支持在组件中使用服务。
依赖注入。

依赖注入是一种方法,它在保持类所需的依赖性的完整性的同时,从类中创建新实例。类所依赖的大部分是服务。Angular使用依赖注入来创建具有所需服务的新组件。
在Angular中,可以通过查看构造函数中参数的类型来判断需要哪个服务。在下面的例子中,HeroListComponent的构造函数需要HeroService。
constructor(private service: HeroService) { }
在Angular中创建组件时,首先需要提供组件所需的服务注入器。
依赖注入是指当所请求的服务实例不存在于容器中时,注入器会创建新的服务并添加到容器中,然后调用使用这些服务作为参数的组件构造函数。这样当所有请求的服务都执行并返回时,可以调用组件的构造函数。
将HeroService注入的过程如下所示。

如果注入器没有HeroService,我们怎么知道如何创建一个新的HeroService呢?
简单来说,我们需要预先注册带有注入器的HeroService提供程序。提供程序具有创建或返回服务(通常是服务本身)的功能。
提供者可以将模块或组件注册。
为了让您可以从任何地方使用相同的服务实例,建议提供者基本上将其添加到根模块中。
providers: [
BackendService,
HeroService,
Logger
],
请改为在组件级别,同样需要将其添加到@Component元数据的providers属性中。
@Component({
moduleId: module.id,
selector: 'hero-list',
templateUrl: 'hero-list.component.html',
providers: [ HeroService ]
})
通过在组件级别注册提供者,可以使每个新创建的组件实例能够获取新服务实例。
为了不忘记,我会列举一些依赖注入的要点。
-
- Dependency injectionはAngularフレームワークの中に張り巡らされていて、どこからでも利用てきる。
インジェクタが核となるメカニズムとなる。
インジェクタは作成したサービスインスタンスのコンテナを保持する。
インジェクタは、プロバイダから新しいサービスのインスタンスを作成できる。
プロバイダはサービスを作るときのレシピになる。
インジェクタを持ったプロバイダを登録する。
概括
我已经学习了Angular应用程序的8个主要组成部分的基础知识。
-
- Modules – モジュール –
-
- Components – コンポーネント –
-
- Templates – テンプレート-
-
- Metadata – メタデータ-
-
- Data binding – データバインディング-
-
- Directives – ディレクティブ-
-
- Services – サービス-
- Dependency injection – 依存性注入-
这些是Angular应用程序的所有基础,作为起点来说已经足够了。然而,仅仅学习这些还不足以完成你应该学习的全部内容。
在这里简单列举了Angular的主要功能和服务的按字母顺序排列的列表。
大部分重要内容已经包含在以下文档中(或在不久的将来会包含)。
Animations: Angularのアニメーションライブラリを使えば、アニメーション技術やCSSの深い知識がなくてもコンポーネントの振る舞いに動きをつけられます。
Change detection: Change detection(変更検知)のドキュメントでは、Angularがコンポーネントのもつプロパティの値の変化をどのようにして決め、どのタイミングで画面を更新しているかといったトピックを扱います。また、非同期で動いているものを中断し、その変更検知がもつ戦略を実行するゾーンの使用方法についても扱います。
Events: イベントのドキュメントでは、イベントを発行、購読するメカニズムを使って、コンポーネントやサービスでイベントを発火させる仕組みを扱っています。
Forms: HTMLベースのバリデーションとdirtyチェックで、複雑なデータ入力のシナリオをサポートします。
HTTP: HTTPクライアントを使ってサーバーサイドのアクションを引き起こし、データの取得、保存といったやり取りをサーバーと行います。
Lifecycle hooks: ライフサイクルフックのインターフェースを実行すると、コンポーネントが生成されてから破壊されるまでの存続期間中に、キー入力のタイミングが利用できます。
Pipes: 画面上にある値の変化によってUXを変更させるには、テンプレートでパイプを使うとよいです。次の例で、currencyパイプの書き方を見てみましょう。
price | currency:’USD’:true
これによって、”42.33″という値は $42.33と表示されます。
Router: ブラウザを離れることなく、クライアントアプリケーション上でページからページへ遷移できます。
Testing: Angularのテストプラットフォームを使って、あなたの作ったアプリケーションの部品が、Angularフレームワーク上でうまく機能しているかどうか、ユニットテストテストを行って試すことができます。
下一步
展示数据