review of architecture.jjade is completed.

This commit is contained in:
Zhimin(Rex) YE 2016-05-17 00:00:11 +01:00
parent 5a0a53a022
commit f3268b5191
1 changed files with 112 additions and 41 deletions

View File

@ -401,6 +401,7 @@ figure
在TypeScript中**装饰器(decorator)**是附加元数据的简易途径。 在TypeScript中**装饰器(decorator)**是附加元数据的简易途径。
下面就是`HeroListComponent`的一些元数据。 下面就是`HeroListComponent`的一些元数据。
+makeExample('architecture/ts/app/hero-list.component.ts', 'metadata', 'app/hero-list.component.ts (元数据)') +makeExample('architecture/ts/app/hero-list.component.ts', 'metadata', 'app/hero-list.component.ts (元数据)')
:marked :marked
Here we see the `@Component` decorator which (no surprise) identifies the class Here we see the `@Component` decorator which (no surprise) identifies the class
@ -453,8 +454,8 @@ code-example(language="html").
so it can get the list of heroes to display. We'll get to dependency injection in a moment. so it can get the list of heroes to display. We'll get to dependency injection in a moment.
* `providers` - 一个数组,包含组件所依赖的用于提供服务的*依赖注入供应商*。 * `providers` - 一个数组,包含组件所依赖的用于提供服务的*依赖注入供应商*。
这是我们告诉Angular该组件的构造函数需要一个`HeroService`服务。所以组件才能获得英雄的列表数据,并显示出来 这是一种方法用来告诉Angular该组件的构造函数需要一个`HeroService`服务,这样组件可以从服务获得英雄的列表数据用来显示
这样我们就在一瞬间完成了依赖注入。 我们一会儿就讲到了依赖注入。
figure figure
img(src="/resources/images/devguide/architecture/template-metadata-component.png" alt="元数据" align="left" style="height:200px; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/template-metadata-component.png" alt="元数据" align="left" style="height:200px; margin-left:-40px;margin-right:10px" )
:marked :marked
@ -462,7 +463,7 @@ figure
to the component class definition. Angular discovers this metadata at runtime and thus knows how to do "the right thing". to the component class definition. Angular discovers this metadata at runtime and thus knows how to do "the right thing".
`@Component`函数接收一个配置对象,并把它转换成元数据,附加到组件类的定义上。 `@Component`函数接收一个配置对象,并把它转换成元数据,附加到组件类的定义上。
Angular在运行期间会找出这份元数据此知道该如何去“做正确的事”。 Angular在运行期间会找出这份元数据此知道该如何去“做正确的事”。
The template, metadata, and component together describe the view. The template, metadata, and component together describe the view.
@ -473,8 +474,9 @@ figure
we'll master as our Angular knowledge grows. we'll master as our Angular knowledge grows.
我们也会沿用类似的风格用其它元数据装饰器来指导Angular的行为。 我们也会沿用类似的风格用其它元数据装饰器来指导Angular的行为。
`@Injectable`、`@Input`、`@Output`、`@RouterConfig`是一些最常用的装饰器。 `@Injectable`、`@Input`、`@Output`和`@RouterConfig`等是一些最常用的装饰器。
随着对Angular认识的逐步深化我们也将逐步掌握它们。 随着对Angular认识的逐步深化我们也将逐步掌握它们。
<br clear="all"> <br clear="all">
:marked :marked
The architectural take-away is that we must add metadata to our code The architectural take-away is that we must add metadata to our code
@ -487,12 +489,14 @@ figure
:marked :marked
## Data Binding ## Data Binding
## 数据绑定 ## 数据绑定
Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses
into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone and a nightmare to into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone and a nightmare to
read as the experienced jQuery programmer can attest. read as the experienced jQuery programmer can attest.
如果没有框架我们就得自己把数据值推送到HTML控件中并把用户的反馈转换成动作并更新值。 如果没有框架我们就得自己把数据值推送到HTML控件中并把用户的反馈转换成动作并更新值。
如果手工写代码来实现这些推/拉逻辑,肯定会枯燥乏味、容易出错,读起来简直是噩梦 —— 写过jQuery的程序员大概都对此深有体会。 如果手工写代码来实现这些推/拉逻辑,肯定会枯燥乏味、容易出错,读起来简直是噩梦 —— 写过jQuery的程序员大概都对此深有体会。
figure figure
img(src="/resources/images/devguide/architecture/databinding.png" alt="数据绑定" style="width:220px; float:left; margin-left:-40px;margin-right:20px" ) img(src="/resources/images/devguide/architecture/databinding.png" alt="数据绑定" style="width:220px; float:left; margin-left:-40px;margin-right:20px" )
:marked :marked
@ -507,6 +511,7 @@ figure
as indicated by the arrows in the diagram. as indicated by the arrows in the diagram.
数据绑定的语法有四种形式。每种形式都有一个方向 —— 从DOM来、到DOM去、双向就像图中的箭头所示意的。 数据绑定的语法有四种形式。每种形式都有一个方向 —— 从DOM来、到DOM去、双向就像图中的箭头所示意的。
<br clear="all"> <br clear="all">
:marked :marked
We saw three forms of data binding in our [example](#template) template: We saw three forms of data binding in our [example](#template) template:
@ -516,14 +521,17 @@ figure
:marked :marked
* The {{hero.name}} "[interpolation](displaying-data.html#interpolation)" * The {{hero.name}} "[interpolation](displaying-data.html#interpolation)"
displays the component's `hero.name` property value within the `<div>` tags. displays the component's `hero.name` property value within the `<div>` tags.
* {{hero.name}} "[插值表达式](displaying-data.html#interpolation)"在`<div>`标签中显示了组件的`hero.name`属性的值。 * {{hero.name}} "[插值表达式](displaying-data.html#interpolation)"在`<div>`标签中显示了组件的`hero.name`属性的值。
* The `[hero]` [property binding](template-syntax.html#property-binding) passes the `selectedHero` from * The `[hero]` [property binding](template-syntax.html#property-binding) passes the `selectedHero` from
the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
* `[hero]`[属性绑定](template-syntax.html#property-binding):把父组件`HeroListComponent`的`selectedHero`传到子组件`HeroDetailComponent`的`hero`属性中。 * `[hero]`[属性绑定](template-syntax.html#property-binding):把父组件`HeroListComponent`的`selectedHero`传到子组件`HeroDetailComponent`的`hero`属性中。
* The `(click)` [event binding](user-input.html#click) calls the Component's `selectHero` method when the user clicks * The `(click)` [event binding](user-input.html#click) calls the Component's `selectHero` method when the user clicks
on a hero's name on a hero's name
* `(click)`[事件绑定](user-input.html#click):当用户点击英雄的名字时,会调用组件的`selectHero`方法。 * `(click)`[事件绑定](user-input.html#click):当用户点击英雄的名字时,会调用组件的`selectHero`方法。
* **Two-way data binding** is an important fourth form * **Two-way data binding** is an important fourth form
@ -540,12 +548,13 @@ figure
The user's changes also flow back to the component, resetting the property to the latest value, The user's changes also flow back to the component, resetting the property to the latest value,
as with event binding. as with event binding.
在双向绑定中,数据属性的值会从具有属性绑定的组件传到输入框。通过事件绑定把最近的值传给属性,用户的修改也能传回组件 在双向绑定中,数据属性的值会从具有属性绑定的组件传到输入框。通过事件绑定,用户的修改被传回到组件,把属性值设置为最新的值
Angular processes *all* data bindings once per JavaScript event cycle, Angular processes *all* data bindings once per JavaScript event cycle,
depth-first from the root of the application component tree. depth-first from the root of the application component tree.
Angular在每个JavaScript事件周期中一次性处理*所有的*数据绑定,它会从组件树的根部进行深度优先遍历来完成更新。 Angular在每个JavaScript事件周期中一次性处理*所有的*数据绑定,它会从组件树的根部开始。进行深度-优先的往上更新。
figure figure
img(src="/resources/images/devguide/architecture/component-databinding.png" alt="数据绑定" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/component-databinding.png" alt="数据绑定" style="float:left; width:300px; margin-left:-40px;margin-right:10px" )
:marked :marked
@ -553,7 +562,8 @@ figure
but it's clear from these examples that data binding plays an important role in communication but it's clear from these examples that data binding plays an important role in communication
between a template and its component ... between a template and its component ...
虽然我们还没看懂所有细节,但从这些范例中至少弄明白一点:数据绑定在模板与相应组件的通讯中扮演了一个很重要的角色。 虽然还不清楚所有细节,但从我们从这些范例中至少弄明白一点:数据绑定在模板与相应组件的交互中扮演了一个很重要的角色。
<br clear="all"> <br clear="all">
figure figure
img(src="/resources/images/devguide/architecture/parent-child-binding.png" alt="父/子绑定" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/parent-child-binding.png" alt="父/子绑定" style="float:left; width:300px; margin-left:-40px;margin-right:10px" )
@ -561,25 +571,29 @@ figure
... ***and*** between parent and child components ... ***and*** between parent and child components
……在父组件与子组件的通讯中***也同样如此***。 ……在父组件与子组件的通讯中***也同样如此***。
<br clear="all"> <br clear="all">
.l-main-section .l-main-section
<a id="directive"></a> <a id="directive"></a>
:marked :marked
## The Directive ## The Directive
## 指令 ## 指令
figure figure
img(src="/resources/images/devguide/architecture/directive.png" alt="父与子" style="float:left; width:150px; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/directive.png" alt="父与子" style="float:left; width:150px; margin-left:-40px;margin-right:10px" )
:marked :marked
Our Angular templates are *dynamic*. When Angular renders them, it transforms the DOM Our Angular templates are *dynamic*. When Angular renders them, it transforms the DOM
according to the instructions given by a **directive**. according to the instructions given by a **directive**.
我们的Angular模板是*动态的*。当Angular渲染它们时它会根据**指令**提供的操作指南对DOM进行修改。 我们的Angular模板是*动态的*。当Angular渲染它们时它会根据**指令**提供的操作指南对DOM进行修改。
A directive is a class with directive metadata. In TypeScript we'd apply the `@Directive` decorator A directive is a class with directive metadata. In TypeScript we'd apply the `@Directive` decorator
to attach metadata to the class. to attach metadata to the class.
指令是一个带有“指令元数据”的类。在TypeScript中我们要通过`@Directive`装饰器把元数据附加到类上。 指令是一个带有“指令元数据”的类。在TypeScript中我们要通过`@Directive`装饰器把元数据附加到类上。
<br clear="all"> <br clear="all">
:marked :marked
We already met one form of directive: the component. A component is a *directive-with-a-template* We already met one form of directive: the component. A component is a *directive-with-a-template*
@ -593,7 +607,8 @@ figure
it is so distinctive and central to Angular applications that we chose it is so distinctive and central to Angular applications that we chose
to separate the component from the directive in our architectural overview. to separate the component from the directive in our architectural overview.
虽然**组件从技术角度说就是一个指令**但它是如此与众不同并在Angular中位于中心地位以至于我们选择把它和指令分别画在我们的架构视图中。 虽然**组件从技术角度说就是一个指令**但组件非常独特并在Angular中位于中心地位以至于我们在架构介绍中把组件从指令中单独开来。
:marked :marked
There are two *other* kinds of directives as well that we call "structural" and "attribute" directives. There are two *other* kinds of directives as well that we call "structural" and "attribute" directives.
@ -611,11 +626,15 @@ figure
We see two built-in structural directives at play in our [example](#template) template: We see two built-in structural directives at play in our [example](#template) template:
我们在[范例](#template)模板中会看到两个内建的结构型指令。 我们在[范例](#template)模板中会看到两个内建的结构型指令。
+makeExample('architecture/ts/app/hero-list.component.1.html', 'structural')(format=".") +makeExample('architecture/ts/app/hero-list.component.1.html', 'structural')(format=".")
:marked :marked
* [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `<div>` per hero in the `heroes` list. * [`*ngFor`](displaying-data.html#ngFor) tells Angular to stamp out one `<div>` per hero in the `heroes` list.
* [`*ngFor`](displaying-data.html#ngFor)告诉Angular为`heroes`列表中的每个英雄生成一个`<div>`标签。 * [`*ngFor`](displaying-data.html#ngFor)告诉Angular为`heroes`列表中的每个英雄生成一个`<div>`标签。
* [`*ngIf`](displaying-data.html#ngIf) includes the `HeroDetail` component only if a selected hero exists. * [`*ngIf`](displaying-data.html#ngIf) includes the `HeroDetail` component only if a selected hero exists.
* [`*ngIf`](displaying-data.html#ngIf)表示只有在已经选择了一个英雄时才会包含`HeroDetail`组件。 * [`*ngIf`](displaying-data.html#ngIf)表示只有在已经选择了一个英雄时才会包含`HeroDetail`组件。
**Attribute** directives alter the appearance or behavior of an existing element. **Attribute** directives alter the appearance or behavior of an existing element.
@ -626,12 +645,13 @@ figure
The `ngModel` directive, which implements two-way data binding, is an example of an attribute directive. The `ngModel` directive, which implements two-way data binding, is an example of an attribute directive.
`ngModel`指令就是Attribute型指令的一个例子它实现了双向数据绑定。 `ngModel`指令就是Attribute型指令的一个例子它实现了双向数据绑定。
+makeExample('architecture/ts/app/hero-detail.component.html', 'ngModel')(format=".") +makeExample('architecture/ts/app/hero-detail.component.html', 'ngModel')(format=".")
:marked :marked
It modifies the behavior of an existing element (typically an `<input>`) It modifies the behavior of an existing element (typically an `<input>`)
by setting its display value property and responding to change events. by setting its display value property and responding to change events.
它修改了现有元素(典型的是`<input>`)的行为让它显示属性值并从change事件中得到回应。 它修改了现有元素(典型的是`<input>`)的行为它设置了显示属性值并对change事件做出相应回应。
Angular ships with a few other directives that either alter the layout structure Angular ships with a few other directives that either alter the layout structure
(e.g. [ngSwitch](template-syntax.html#ngSwitch)) (e.g. [ngSwitch](template-syntax.html#ngSwitch))
@ -643,46 +663,57 @@ figure
And of course we can write our own directives. And of course we can write our own directives.
而且,当然,我们还能写自己的指令。 当然,我们也能编写自己的指令。
.l-main-section .l-main-section
<a id="service"></a> <a id="service"></a>
:marked :marked
## The Service ## The Service
## 服务 ## 服务
figure figure
img(src="/resources/images/devguide/architecture/service.png" alt="服务" style="float:left; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/service.png" alt="服务" style="float:left; margin-left:-40px;margin-right:10px" )
:marked :marked
"Service" is a broad category encompassing any value, function or feature that our application needs. "Service" is a broad category encompassing any value, function or feature that our application needs.
“服务”分为很多种,包括:值、函数,以及应用所需的任何特性。 “服务”分为很多种,包括:值、函数,以及应用所需的特性。
Almost anything can be a service. Almost anything can be a service.
A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well. A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well.
几乎任何东西都可以是一个服务。 几乎任何东西都可以是一个服务。
典型的服务是一个类,具有专注的、经过良好定义的用途。它应该做一些具体的事情,并做好。 典型的服务是一个类,具有专注的、良好定义的用途。它应该做一件具体的事情,把它做好。
<br clear="all"> <br clear="all">
:marked :marked
Examples include: Examples include:
例如: 例如:
* logging service * logging service
* 日志服务 * 日志服务
* data service * data service
* 数据服务 * 数据服务
* message bus * message bus
* 消息总线 * 消息总线
* tax calculator * tax calculator
* 税款计算器 * 税款计算器
* application configuration * application configuration
* 应用程序配置 * 应用程序配置
There is nothing specifically *Angular* about services. Angular itself has no definition of a *service*. There is nothing specifically *Angular* about services. Angular itself has no definition of a *service*.
There is no *ServiceBase* class. There is no *ServiceBase* class.
Angular对于服务没什么特别的要求。 服务没有什么特别属于Angular的特征。Angular本身对于服务也没有什么定义。
Angular本身对于服务也没有什么定义。
它甚至都没有*ServiceBase*类。 它甚至都没有*ServiceBase*类。
Yet services are fundamental to any Angular application. Yet services are fundamental to any Angular application.
@ -692,13 +723,15 @@ figure
Here's an example of a service class that logs to the browser console Here's an example of a service class that logs to the browser console
这里是一个“服务”类的范例,用于把日志记录到浏览器的控制台: 这里是一个“服务”类的范例,用于把日志记录到浏览器的控制台:
+makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (只有类)')(format=".") +makeExample('architecture/ts/app/logger.service.ts', 'class', 'app/logger.service.ts (只有类)')(format=".")
:marked :marked
Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://exploringjs.com/es6/ch_promises.html). Here's a `HeroService` that fetches heroes and returns them in a resolved [promise](http://exploringjs.com/es6/ch_promises.html).
The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work. The `HeroService` depends on the `LoggerService` and another `BackendService` that handles the server communication grunt work.
下面是一个`HeroService`类,用于获取英雄数据,并通过一个已解的[承诺Promise](http://exploringjs.com/es6/ch_promises.html)返回它们。 下面是一个`HeroService`类,用于获取英雄数据,并通过一个已解的[承诺Promise](http://exploringjs.com/es6/ch_promises.html)返回它们。
`HeroService`还依赖于`LoggerService`和另一个用来处理服务器通讯工作的`BackendService`。 `HeroService`还依赖于`LoggerService`和另一个用来处理服务器通讯工作的`BackendService`。
+makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (只有类)')(format=".") +makeExample('architecture/ts/app/hero.service.ts', 'class', 'app/hero.service.ts (只有类)')(format=".")
:marked :marked
Services are everywhere. Services are everywhere.
@ -710,15 +743,15 @@ figure
They delegate such tasks to services. They delegate such tasks to services.
我们的组件是服务的主要消费者。它们依赖服务来处理大多数“苦差事”。 我们的组件是服务的主要消费者。它们依赖服务来处理大多数“苦差事”。
它们不需要从服务器获得数据,它们不需要验证输入,它们不需要直接往控制台写日志。 它们自己不需要从服务器获得数据,不需要验证输入,不需要直接往控制台写日志。
它们只要把任务委托给这些服务。 它们把任务委托给服务。
A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template) A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template)
and the application logic (which often includes some notion of a "model"). A good component presents and the application logic (which often includes some notion of a "model"). A good component presents
properties and methods for data binding. It delegates everything non-trivial to services. properties and methods for data binding. It delegates everything non-trivial to services.
组件的任务就是提供用户体验仅此而已。它介于视图由模板渲染和应用逻辑通常包括“模型model”的观念之间。 组件的任务就是提供用户体验仅此而已。它介于视图由模板渲染和应用逻辑通常包括“模型model”的观念之间。
设计良好的组件会提供属性和方法供数据绑定,而把那些不重要的事情都委托给服务。 设计良好的组件为数据绑定提供属性和方法,把那些其他对它们不重要的事情都委托给服务。
Angular doesn't *enforce* these principles. Angular doesn't *enforce* these principles.
It won't complain if we write a "kitchen sink" component with 3000 lines. It won't complain if we write a "kitchen sink" component with 3000 lines.
@ -729,13 +762,15 @@ figure
Angular does help us *follow* these principles by making it easy to factor our Angular does help us *follow* these principles by making it easy to factor our
application logic into services and make those services available to components through *dependency injection*. application logic into services and make those services available to components through *dependency injection*.
Angular帮助我们*追随*这些原则 —— 它让我们能更轻易的把应用逻辑拆分成组件,并通过*依赖注入*来让这些服务在组件中可用 Angular帮助我们*追随*这些原则 —— 它让我们能更轻易的把应用逻辑拆分到服务,并通过*依赖注入*来在组件中使用这些服务
.l-main-section .l-main-section
<a id="dependency-injection"></a> <a id="dependency-injection"></a>
:marked :marked
## Dependency Injection ## Dependency Injection
## 依赖注入 ## 依赖注入
figure figure
img(src="/resources/images/devguide/architecture/dependency-injection.png" alt="服务" style="float:left; width:200px; margin-left:-40px;margin-right:10px" ) img(src="/resources/images/devguide/architecture/dependency-injection.png" alt="服务" style="float:left; width:200px; margin-left:-40px;margin-right:10px" )
:marked :marked
@ -745,12 +780,13 @@ figure
“依赖注入”是提供类的新实例的一种方式,还负责处理好它所需的全部依赖。大多数依赖都是服务。 “依赖注入”是提供类的新实例的一种方式,还负责处理好它所需的全部依赖。大多数依赖都是服务。
Angular也使用依赖注入提供我们需要的组件包括组件所需的服务。 Angular也使用依赖注入提供我们需要的组件包括组件所需的服务。
<br clear="all"> <br clear="all">
:marked :marked
In TypeScript, Angular can tell which services a component needs by looking at the types of its constructor parameters. In TypeScript, Angular can tell which services a component needs by looking at the types of its constructor parameters.
For example, the constructor of our `HeroListComponent` needs the `HeroService`: For example, the constructor of our `HeroListComponent` needs the `HeroService`:
借助TypeScriptAngular能通过查看构造函数的参数类型告诉组件需要哪些服务。 借助TypeScriptAngular能通过查看构造函数的参数类型,并得知组件需要哪些服务。
例如,我们`HeroListComponent`组件的构造函数需要`HeroService` 例如,我们`HeroListComponent`组件的构造函数需要`HeroService`
+makeExample('architecture/ts/app/hero-list.component.ts', 'ctor', 'app/hero-list.component (构造函数)')(format=".") +makeExample('architecture/ts/app/hero-list.component.ts', 'ctor', 'app/hero-list.component (构造函数)')(format=".")
:marked :marked
@ -767,13 +803,14 @@ figure
This is what we mean by *dependency injection*. This is what we mean by *dependency injection*.
注入器会维护一个服务实例的容器,存放着以前创建的实例。 注入器会维护一个服务实例的容器,存放着以前创建的实例。
如果容器中还没有所请求的服务实例注入器就会创建一个并且添加到容器中然后把这个服务返回给Angular。 如果容器中还没有所请求的服务实例,注入器就会创建一个服务实例并且添加到容器中然后把这个服务返回给Angular。
当所有的服务都被解析完并返回时Angular会以这些服务为参数去调用组件的构造函数。 当所有的服务都被解析完并返回时Angular会以这些服务为参数去调用组件的构造函数。
这就是我们称其为 *依赖注入* 的原因 这就是我们所说的*依赖注入*
The process of `HeroService` injection looks a bit like this: The process of `HeroService` injection looks a bit like this:
`HeroService`注入的过程看起来有点像这样: `HeroService`注入的过程看起来有点像这样:
figure figure
img(src="/resources/images/devguide/architecture/injector-injects.png" alt="服务" ) img(src="/resources/images/devguide/architecture/injector-injects.png" alt="服务" )
:marked :marked
@ -784,26 +821,28 @@ figure
In brief, we must have previously registered a **provider** of the `HeroService` with the `Injector`. In brief, we must have previously registered a **provider** of the `HeroService` with the `Injector`.
A provider is something that can create or return a service, typically the service class itself. A provider is something that can create or return a service, typically the service class itself.
简单的说,我们必须有以前通过注入器注册过的`HeroService`**供应商Provider**。 简单的说,我们必须有:之前通过注入器注册过的`HeroService`的**供应商Provider**。
供应商就是某些我们用来创建并返回服务的东西,通常就是这个“服务类”本身。 供应商可以创建并返回服务,通常返回的就是这个“服务类”本身。
We can register providers at any level of the application component tree. We can register providers at any level of the application component tree.
We often do so at the root when we bootstrap the application so that We often do so at the root when we bootstrap the application so that
the same instance of a service is available everywhere. the same instance of a service is available everywhere.
我们可以在应用程序的组件树中任何级别上注册供应商。 我们可以在应用程序的组件树中任何级别上注册供应商。
我们通常在应用启动时注册在根组件上,以便此服务的同一个实例在任何地方都是可用的。 当我们需要一个服务的同一个实例在任何地方都是可用时,我们通常在应用引导程序中注册它。
+makeExample('architecture/ts/app/main.ts', 'bootstrap','app/main.ts (节选)')(format=".") +makeExample('architecture/ts/app/main.ts', 'bootstrap','app/main.ts (节选)')(format=".")
:marked :marked
Alternatively, we might register at a component level ... Alternatively, we might register at a component level ...
或者,我们也可以把它注册在组件层…… 或者,我们也可以把它注册在组件层……
+makeExample('architecture/ts/app/hero-list.component.ts', 'providers','app/hero-list.component.ts (节选)')(format=".") +makeExample('architecture/ts/app/hero-list.component.ts', 'providers','app/hero-list.component.ts (节选)')(format=".")
:marked :marked
... in which case we get a new instance of the ... in which case we get a new instance of the
service with each new instance of that component. service with each new instance of that component.
…… 在这种情况下,那个组件的每一个新实例都会有一个服务的新实例。 …… 在这种情况下,那个组件的每一个新实例都会有一个(在该组件注册的)服务的新实例。
We've vastly over-simplified dependency injection for this overview. We've vastly over-simplified dependency injection for this overview.
We can learn the full story in the [Dependency Injection](dependency-injection.html) chapter. We can learn the full story in the [Dependency Injection](dependency-injection.html) chapter.
@ -814,56 +853,87 @@ figure
The points to remember are: The points to remember are:
需要记住的要点是: 需要记住的要点是:
* dependency injection is wired into the framework and used everywhere.<br><br> * dependency injection is wired into the framework and used everywhere.<br><br>
* 依赖注入渗透在整个框架中,并且随处可用。<br><br> * 依赖注入渗透在整个框架中,并且随处可用。<br><br>
* the `Injector` is the main mechanism. * the `Injector` is the main mechanism.
* 注入器`Injector`是本机制的核心。 * 注入器`Injector`是本机制的核心。
* an injector maintains a *container* of service instances that it created. * an injector maintains a *container* of service instances that it created.
* 注入器负责维护一个*容器*,用于存放它创建过的服务实例。 * 注入器负责维护一个*容器*,用于存放它创建过的服务实例。
* an injector can create a new service instance using a *provider*. * an injector can create a new service instance using a *provider*.
* 注入器能使用*供应商*创建一个新的服务实例。 * 注入器能使用*供应商*创建一个新的服务实例。
* a *provider* is a recipe for creating a service. * a *provider* is a recipe for creating a service.
* *供应商*是一个用于创建服务的“配方”。 * *供应商*是一个用于创建服务的“配方”。
* we register *providers* with injectors. * we register *providers* with injectors.
* 我们通过注入器注册*供应商*。
* 我们通过注入器来注册*供应商*。
<a id="other-stuff"></a> <a id="other-stuff"></a>
.l-main-section .l-main-section
:marked :marked
## Wrap up ## Wrap up
## 总结 ## 总结
We've learned just a bit about the eight main building blocks of an Angular application We've learned just a bit about the eight main building blocks of an Angular application
我们学到的这些只是关于应用的八个主要构造块的一点皮毛 我们学到的这些只是关于应用的八个主要构造块的一点皮毛
1. [Module](#module) 1. [Module](#module)
1. [模块Module](#module)
1. [模块](#module)
1. [Component](#component) 1. [Component](#component)
1. [组件Component](#component)
1. [组件](#component)
1. [Template](#template) 1. [Template](#template)
1. [模板Template](#template)
1. [模板=](#template)
1. [Metadata](#metadata) 1. [Metadata](#metadata)
1. [元数据Metadata](#metadata)
1. [元数据=](#metadata)
1. [Data Binding](#data-binding) 1. [Data Binding](#data-binding)
1. [数据绑定Data Binding](#data-binding)
1. [数据绑定=](#data-binding)
1. [Directive](#directive) 1. [Directive](#directive)
1. [指令Directive](#directive)
1. [指令=](#directive)
1. [Service](#service) 1. [Service](#service)
1. [服务Service](#service)
1. [服务=](#service)
1. [Dependency Injection](#dependency-injection) 1. [Dependency Injection](#dependency-injection)
1. [依赖注入Dependency Injection](#dependency-injection)
1. [依赖注入=](#dependency-injection)
That's a foundation for everything else in an Angular application That's a foundation for everything else in an Angular application
and it's more than enough to get going. and it's more than enough to get going.
But it doesn't include everything we'll need or want to know. But it doesn't include everything we'll need or want to know.
这是Angular应用中所有其它东西的基础。要继续向前这已经绰绰有余了。 这是Angular应用中所有其它东西的基础这些对开端使用Angular 2已经绰绰有余了。
但它仍然没有包含我们将要用到或想知道的全部。 但它仍然没有包含我们需要的或想知道的全部。
<a id="other-stuff"></a> <a id="other-stuff"></a>
.l-main-section .l-main-section
:marked :marked
## The Other Stuff ## The Other Stuff
## 其它东西 ## 其它东西
Here is a brief, alphabetical list of other important Angular features and services. Here is a brief, alphabetical list of other important Angular features and services.
@ -896,7 +966,7 @@ figure
>**Events** - The DOM raises events. So can components and services. Angular offers mechanisms for >**Events** - The DOM raises events. So can components and services. Angular offers mechanisms for
publishing and subscribing to events including an implementation of the [RxJS Observable](https://github.com/zenparsing/es-observable) proposal. publishing and subscribing to events including an implementation of the [RxJS Observable](https://github.com/zenparsing/es-observable) proposal.
>**事件Events** - DOM能触发事件组件和服务也能。Angular提供的事件发布与订阅机制还包括[RxJS可观察Observable](https://github.com/zenparsing/es-observable)方案的一个实 >**事件Events** - DOM能触发事件组件和服务也能。Angular提供的事件发布与订阅机制还包括[RxJS可观察Observable](https://github.com/zenparsing/es-observable)方案的一个实
>**[Forms](forms.html)** - Support complex data entry scenarios with HTML-based validation and dirty checking. >**[Forms](forms.html)** - Support complex data entry scenarios with HTML-based validation and dirty checking.
@ -916,6 +986,7 @@ figure
this `currency` pipe expression, this `currency` pipe expression,
>**[管道Pipes](pipes.html)** - 这种服务会转换值以供显示。我们可以把管道放在模板中,以增强用户体验。比如这个`currency`管道表达式, >**[管道Pipes](pipes.html)** - 这种服务会转换值以供显示。我们可以把管道放在模板中,以增强用户体验。比如这个`currency`管道表达式,
<div style="margin-left:40px"> <div style="margin-left:40px">
code-example(language="javascript" linenumbers="."). code-example(language="javascript" linenumbers=".").
price | currency:'USD':true price | currency:'USD':true
@ -928,4 +999,4 @@ code-example(language="javascript" linenumbers=".").
>**[Testing](../testing/index.html)** - Angular provides a testing library for "unit testing" our application parts as they >**[Testing](../testing/index.html)** - Angular provides a testing library for "unit testing" our application parts as they
interact with the Angular framework. interact with the Angular framework.
>**[Testing](../testing/index.html)** - Angular提供了一个用于对我们应用中的各个部分进行“单元测试”的测试库就像它们与Angular框架交互时一样 >**[Testing](../testing/index.html)** - Angular提供了一个测试库在程序各个部分与Angular框架交互同时用来“单元测试”它们