把所有全角括号改成了半角的
This commit is contained in:
parent
a7e9ff78ff
commit
bc2e4b83c0
|
@ -1,61 +0,0 @@
|
|||
.l-main-section
|
||||
h2 Get Help Using Angular
|
||||
h2 获得使用Angular的帮助
|
||||
|
||||
p.
|
||||
We have an incredible community of developers who are passionate about solving problems.
|
||||
We recommend some of the following methods to get help with Angular.
|
||||
我们有一个难以置信的开发者社区,他们充满激情的解决问题。我们建议您通过下列方式获取关于Angular的帮助:
|
||||
|
||||
|
||||
.l-sub-section
|
||||
h3 Angular Google Group
|
||||
|
||||
ol
|
||||
li.
|
||||
Search the archive first.
|
||||
It's likely that your question has already been answered.
|
||||
li.
|
||||
先搜索文档。
|
||||
你的问题很可能有别人问过了。
|
||||
li.
|
||||
To avoid the spam moderation queue,
|
||||
don't include code directly in your email. (See #3)
|
||||
li.
|
||||
为了避免被当成垃圾邮件,请不要在你的邮件中包含代码。(参见下一条)
|
||||
li.
|
||||
Link to a live code example that demonstrates your problem or question,
|
||||
so you'll get an answer faster.
|
||||
<a href="http://plnkr.co/edit/jISF8yxbVGmarpBbqsYW?p=preview">Use this template</a>.
|
||||
li.
|
||||
给出一个“活代码范例”的链接,来演示你的难题或问题,那样你会更快的获得答案。
|
||||
<a href="http://plnkr.co/edit/jISF8yxbVGmarpBbqsYW?p=preview">使用这个模板</a>。
|
||||
li.
|
||||
If you get help, help others. Good karma rulez!
|
||||
li.
|
||||
如果得到了帮助,别忘了帮助别人。人生金律!
|
||||
|
||||
a(href="https://groups.google.com/forum/#!forum/angular" class="button button-primary" md-button) View the Google Group
|
||||
|
||||
a(href="https://groups.google.com/forum/#!forum/angular" class="button button-primary" md-button) 访问Google Group
|
||||
|
||||
.l-sub-section
|
||||
h3 Angular Chat Room
|
||||
h3 Angular聊天室
|
||||
|
||||
p Talk in real time with other Angular developers.
|
||||
p 和其他Angular开发者实时聊天。
|
||||
|
||||
a(href="http://webchat.freenode.net/?channels=angularjs&uio=d4" class="button button-primary" md-button) View the Chat Room
|
||||
a(href="http://webchat.freenode.net/?channels=angularjs&uio=d4" class="button button-primary" md-button) 访问聊天室
|
||||
|
||||
|
||||
.l-sub-section
|
||||
h3 Report an Issue
|
||||
h3 报告问题
|
||||
|
||||
p If you run into an issue or have a feature request, you can create a new issue on our GitHub repository.
|
||||
p 如果你遇到了问题或者需要某些特性,你可以在我们的Github仓库中创建一个新的issue。
|
||||
|
||||
a(href="https://github.com/angular/angular/issues" class="button button-primary" md-button) Report an Issue
|
||||
a(href="https://github.com/angular/angular/issues" class="button button-primary" md-button) 报告问题
|
|
@ -9,7 +9,7 @@
|
|||
on top of each other.
|
||||
p.
|
||||
请在文档中严谨的使用警告。这意味着只在重要的场合用它吸引注意力。
|
||||
不要用警告表现多行内容(使用插图代替),也不要把它们堆叠在一起。
|
||||
不要用警告表现多行内容(使用插图代替),也不要把它们堆叠在一起。
|
||||
.showcase-content
|
||||
.l-sub-section
|
||||
h3 Adding an alert
|
||||
|
|
|
@ -139,7 +139,7 @@ table(width="100%")
|
|||
These practices together prevent our code from
|
||||
polluting the global scope.
|
||||
|
||||
我们经常在`window`对象上附加一个应用程序命名空间对象(比如`"app"`),然后把所要共享一切都附加到这个对象上。
|
||||
我们经常在`window`对象上附加一个应用程序命名空间对象(比如`"app"`),然后把所要共享一切都附加到这个对象上。
|
||||
也可以把我们的代码包装进一个[立即调用函数表达式IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)。
|
||||
这些实践可以防止我们的代码污染全局作用域。
|
||||
|
||||
|
@ -210,7 +210,7 @@ table(width="100%")
|
|||
ES5 JavaScript has no classes. We use the constructor
|
||||
pattern instead which works with Angular 2 as well as classes do.
|
||||
|
||||
ES5 JavaScript不支持类,我们使用构造器模式(constructor pattern)来代替它,它可以和类一样与Angular 2协同工作。
|
||||
ES5 JavaScript不支持类,我们使用构造器模式(constructor pattern)来代替它,它可以和类一样与Angular 2协同工作。
|
||||
|
||||
+makeExample('cb-ts-to-js/js/app/hero.component.js', 'constructorproto')(format="." )
|
||||
|
||||
|
@ -382,7 +382,7 @@ table(width="100%")
|
|||
There is no equivalent of a property decorator in ES5 JavaScript. Instead,
|
||||
we add comparable information to the `Component` (or `Directive`) metadata.
|
||||
|
||||
在ES5 JavaScript里并没有属性装饰器的等价物,但我们可以往`Component`(或者`Directive`)的元数据中添加对应的信息。
|
||||
在ES5 JavaScript里并没有属性装饰器的等价物,但我们可以往`Component`(或者`Directive`)的元数据中添加对应的信息。
|
||||
|
||||
In this example, we add `inputs` and `outputs` array attributes
|
||||
containing the input and output property names.
|
||||
|
|
|
@ -518,7 +518,7 @@ table(width="100%")
|
|||
and event binding (from the view to the component), thereby giving us two-way binding.
|
||||
|
||||
在Angular 2中,**双向绑定**使用[()]标记出来,它被形象的比作“盒子中的香蕉”。
|
||||
这种语法是一个简写形式,用来同时定义一个属性绑定(从组件到视图)和一个事件绑定(从视图到组件),因此,我们得到了双向绑定。
|
||||
这种语法是一个简写形式,用来同时定义一个属性绑定(从组件到视图)和一个事件绑定(从视图到组件),因此,我们得到了双向绑定。
|
||||
|
||||
For more information on two-way binding with ngModel see [Template Syntax](../guide/template-syntax.html#ngModel).
|
||||
|
||||
|
@ -551,7 +551,7 @@ table(width="100%")
|
|||
|
||||
Angular 2中的`*ngFor`指令类似于Angular 1中的`ng-repeat`指令。
|
||||
它为指定集合中的每一个条目重复渲染了相关的DOM元素。
|
||||
更准确的说,它把被界定出来的元素(这个例子中是`tr`)及其内容转成了一个模板,并使用那个模板来为列表中的每一个条目实例化一个视图。
|
||||
更准确的说,它把被界定出来的元素(这个例子中是`tr`)及其内容转成了一个模板,并使用那个模板来为列表中的每一个条目实例化一个视图。
|
||||
|
||||
Notice the other syntax differences:
|
||||
The (*) before `ngFor` is required;
|
||||
|
@ -1000,7 +1000,7 @@ table(width="100%")
|
|||
In Angular 1, we often defined an immediately invoked function expression (or IIFE) around our controller code.
|
||||
This kept our controller code out of the global namespace.
|
||||
|
||||
在Angular 1中,我们通常会定义一个立即调用的函数表达式(IIFE)来包裹我们的控制器代码。
|
||||
在Angular 1中,我们通常会定义一个立即调用的函数表达式(IIFE)来包裹我们的控制器代码。
|
||||
这样让控制器代码不会污染全局命名空间。
|
||||
|
||||
td
|
||||
|
|
|
@ -66,7 +66,7 @@ include ../_util-fns
|
|||
:marked
|
||||
The second `@Input` aliases the child component property name `masterName` as `'master'`.
|
||||
|
||||
第二个`@Input`为子组件的属性名`masterName`指定一个别名`master`(译者注:不推荐为起别名,请参见风格指南).
|
||||
第二个`@Input`为子组件的属性名`masterName`指定一个别名`master`(译者注:不推荐为起别名,请参见风格指南).
|
||||
|
||||
The `HeroParentComponent` nests the child `HeroChildComponent` inside an `*ngFor` repeater, binding its `master` string property to the child's `master` alias and each iteration's `hero` instance to the child's `hero` property.
|
||||
|
||||
|
@ -203,7 +203,7 @@ figure.image-display
|
|||
|
||||
The child component exposes an `EventEmitter` property with which it `emits`events when something happens. The parent binds to that event property and reacts to those events.
|
||||
|
||||
子组件暴露一个`EventEmitter`属性,当事件发生时,子组件利用该属性`emits`(向上弹射)事件。父组件绑定到这个事件属性,并在事件发生时作出回应。
|
||||
子组件暴露一个`EventEmitter`属性,当事件发生时,子组件利用该属性`emits`(向上弹射)事件。父组件绑定到这个事件属性,并在事件发生时作出回应。
|
||||
|
||||
The child's `EventEmitter` property is an ***output property***, typically adorned with an [@Output decoration](../guide/template-syntax.html#inputs-outputs) as seen in this `VoterComponent`:
|
||||
|
||||
|
@ -214,7 +214,7 @@ figure.image-display
|
|||
:marked
|
||||
Clicking a button triggers emission of a `true` or `false` (the boolean *payload*).
|
||||
|
||||
点击按钮会触发`true`或`false`(布尔型*有效载荷*)的事件。
|
||||
点击按钮会触发`true`或`false`(布尔型*有效载荷*)的事件。
|
||||
|
||||
The parent `VoteTakerComponent` binds an event handler (`onVoted`) that responds to the child event payload (`$event`) and updates a counter.
|
||||
|
||||
|
@ -225,7 +225,7 @@ figure.image-display
|
|||
:marked
|
||||
The framework passes the event argument — represented by `$event` — to the handler method, and the method processes it:
|
||||
|
||||
框架(Angular)把事件参数(用`$event`表示)传给事件处理方法,这个方法会处理:
|
||||
框架(Angular)把事件参数(用`$event`表示)传给事件处理方法,这个方法会处理:
|
||||
|
||||
figure.image-display
|
||||
img(src="/resources/images/cookbooks/component-communication/child-to-parent.gif" alt="Child-to-parent")
|
||||
|
@ -407,7 +407,7 @@ a(id="countdown-tests")
|
|||
:marked
|
||||
The `MissionControlComponent` both provides the instance of the service that it shares with its children (through the `providers` metadata array) and injects that instance into itself through its constructor:
|
||||
|
||||
`MissionControlComponent`提供服务的实例,并将其共享给它的子组件(通过`providers`元数据数组),子组件可以通过构造函数将该实例注入到自身。
|
||||
`MissionControlComponent`提供服务的实例,并将其共享给它的子组件(通过`providers`元数据数组),子组件可以通过构造函数将该实例注入到自身。
|
||||
|
||||
+makeExample('cb-component-communication/ts/app/missioncontrol.component.ts')
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ include ../_util-fns
|
|||
with a suitable package loader such as `systemjs` or `webpack`.
|
||||
Learn why [below](#why-default).
|
||||
|
||||
如果把应用构建成`commonjs`模块,并用一个合适的包加载器(比如`systemjs`或`webpack`)加载那些模块,我们就可以用相对路径。
|
||||
如果把应用构建成`commonjs`模块,并用一个合适的包加载器(比如`systemjs`或`webpack`)加载那些模块,我们就可以用相对路径。
|
||||
[在下方](#why-default)可以学到原理。
|
||||
|
||||
The Angular 2 CLI uses these technologies and defaults to the
|
||||
|
|
|
@ -134,7 +134,7 @@ include ../_util-fns
|
|||
(the `LoggerService`, `UserContext`, and the `UserService`)
|
||||
in the `@Component` metadata `providers` array.
|
||||
|
||||
在下面的例子中,通过`@Component`元数据的`providers`数组导入和注册了几个服务(`LoggerService`, `UserContext`和`UserService`)。
|
||||
在下面的例子中,通过`@Component`元数据的`providers`数组导入和注册了几个服务(`LoggerService`, `UserContext`和`UserService`)。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/app.component.ts','import-services','app/app.component.ts (excerpt)')(format='.')
|
||||
:marked
|
||||
|
@ -176,7 +176,7 @@ include ../_util-fns
|
|||
but (a) aren't conceptually part of the application and (b) that we could change later without
|
||||
altering the essential logic of the application.
|
||||
|
||||
使用外部模块时,如果满足下面两个条件,就应该在引导过程中注册:a)它在概念上不是我们程序的一部分,以及 b)将来我们可能要在不改变主要应用逻辑的情况下更换它。
|
||||
使用外部模块时,如果满足下面两个条件,就应该在引导过程中注册:a)它在概念上不是我们程序的一部分,以及 b)将来我们可能要在不改变主要应用逻辑的情况下更换它。
|
||||
|
||||
For example, we might configure the Component Router with different
|
||||
[location strategies](../guide/router.html#location-strategy) based on environmental factors.
|
||||
|
@ -189,7 +189,7 @@ include ../_util-fns
|
|||
We'll switch to the real backend in production.
|
||||
The application shouldn't know or care one way or the other.
|
||||
|
||||
在开发过程中,可以偷偷把一个假的带样本数据的HTTP后端嵌入进来,以代替对一个远程服务器(可能还不存在)进行http查询。我们在产品发布时再切换到真正的后端。应用程序不用知道也不用管正在跟哪个后端打交道。
|
||||
在开发过程中,可以偷偷把一个假的带样本数据的HTTP后端嵌入进来,以代替对一个远程服务器(可能还不存在)进行http查询。我们在产品发布时再切换到真正的后端。应用程序不用知道也不用管正在跟哪个后端打交道。
|
||||
|
||||
See both examples in the following `main.ts`
|
||||
where we list their service providers in an array in the second parameter of the `bootstrap` method.
|
||||
|
@ -229,7 +229,7 @@ a(id="nested-dependencies")
|
|||
The `UserContext` in turn has dependencies on both the `LoggerService` (again) and
|
||||
a `UserService` that gathers information about a particular user.
|
||||
|
||||
`UserContext`有两个依赖`LoggerService`(再一次)和负责获取特定用户信息的`UserService`。
|
||||
`UserContext`有两个依赖`LoggerService`(再一次)和负责获取特定用户信息的`UserService`。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/user-context.service.ts','injectables','user-context.service.ts (injection)')(format='.')
|
||||
|
||||
|
@ -314,7 +314,7 @@ figure.image-display
|
|||
So a particular service can be *provided* (and created) at any component level and multiple times
|
||||
if provided in multiple components.
|
||||
|
||||
但是Angular应用程序有多个依赖注入器,组织成一个与组件树平行的树状结构。所以,可以在任何组件级别*提供*(和建立)特定的服务。如果在多个组件中注入,服务就会被新建出多个实例,分别提供给不同的组件。
|
||||
但是Angular应用程序有多个依赖注入器,组织成一个与组件树平行的树状结构。所以,可以在任何组件级别*提供*(和建立)特定的服务。如果在多个组件中注入,服务就会被新建出多个实例,分别提供给不同的组件。
|
||||
|
||||
By default, a service dependency provided in one component is visible to all of its child components and
|
||||
Angular injects the same service instance into all child components that ask for that service.
|
||||
|
@ -342,7 +342,7 @@ figure.image-display
|
|||
When Angular creates the `HeroesBaseComponent`, it also creates a new instance of `HeroService`
|
||||
that is visible only to the component and its children (if any).
|
||||
|
||||
当Angular新建`HeroBaseComponent`的时候,它会同时新建一个`HeroService`实例,该实例只在该组件及其子组件(如果有)中可见。
|
||||
当Angular新建`HeroBaseComponent`的时候,它会同时新建一个`HeroService`实例,该实例只在该组件及其子组件(如果有)中可见。
|
||||
|
||||
We could also provide the `HeroService` to a *different* component elsewhere in the application.
|
||||
That would result in a *different* instance of the service, living in a *different* injector.
|
||||
|
@ -374,7 +374,7 @@ figure.image-display
|
|||
.l-main-section
|
||||
:marked
|
||||
## Multiple service instances (sandboxing)
|
||||
## 多个服务实例(sandboxing)
|
||||
## 多个服务实例(sandboxing)
|
||||
|
||||
Sometimes we want multiple instances of a service at *the same level of the component hierarchy*.
|
||||
|
||||
|
@ -411,7 +411,7 @@ figure.image-display
|
|||
Each `HeroBioComponent` gets its *own* `HeroCacheService` instance
|
||||
by listing the `HeroCacheService` in its metadata `providers` array.
|
||||
|
||||
通过在自己的元数据(metadata)`providers`数组里面列出`HeroCacheService`, 每个`HeroBioComponent`就能*拥有*自己独立的`HeroCacheService`实例。
|
||||
通过在自己的元数据(metadata)`providers`数组里面列出`HeroCacheService`, 每个`HeroBioComponent`就能*拥有*自己独立的`HeroCacheService`实例。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-bio.component.ts','component','app/hero-bio.component.ts')
|
||||
:marked
|
||||
|
@ -453,13 +453,13 @@ a(id="qualify-dependency-lookup")
|
|||
used individually or together.
|
||||
|
||||
大部分时候,我们确实*想要*这个行为。
|
||||
但是有时候,我们需要限制这个(依赖)查找逻辑,且/或提供一个缺失的依赖。
|
||||
但是有时候,我们需要限制这个(依赖)查找逻辑,且/或提供一个缺失的依赖。
|
||||
单独或联合使用`@Host`和`@Optional`限定型装饰器,我们就可以修改Angular的查找行为。
|
||||
|
||||
The `@Optional` decorator tells Angular to continue when it can't find the dependency.
|
||||
Angular sets the injection parameter to `null` instead.
|
||||
|
||||
当Angular找不到依赖时,`@Optional`装饰器会告诉Angular继续执行。Angular把此注入参数设置为`null`(而不用默认的抛出错误的行为)。
|
||||
当Angular找不到依赖时,`@Optional`装饰器会告诉Angular继续执行。Angular把此注入参数设置为`null`(而不用默认的抛出错误的行为)。
|
||||
|
||||
The `@Host` decorator stops the upward search at the *host component*.
|
||||
|
||||
|
@ -490,7 +490,7 @@ a(id="qualify-dependency-lookup")
|
|||
Angular *projects* (*transcludes*) the corresponding `HeroContactComponent` into the `HeroBioComponent` view,
|
||||
placing it in the `<ng-content>` slot of the `HeroBioComponent` template:
|
||||
|
||||
我们在`<hero-bio>`标签中插入了`<hero-contact>`元素。Angular就会把相应的`HeroContactComponent`*投影*(*transclude*)进`HeroBioComponent`的视图里,
|
||||
我们在`<hero-bio>`标签中插入了`<hero-contact>`元素。Angular就会把相应的`HeroContactComponent`*投影*(*transclude*)进`HeroBioComponent`的视图里,
|
||||
将它放在`HeroBioComponent`模板的`<ng-content>`标签槽里。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-bio.component.ts','template','app/hero-bio.component.ts (template)')(format='.')
|
||||
|
@ -504,7 +504,7 @@ figure.image-display
|
|||
:marked
|
||||
Here's the `HeroContactComponent` which demonstrates the qualifying decorators that we're talking about in this section:
|
||||
|
||||
下面的`HeroContactComponent`,示范了我们在本节一直在讨论的限定型装饰器(@Optional和@Host):
|
||||
下面的`HeroContactComponent`,示范了我们在本节一直在讨论的限定型装饰器(@Optional和@Host):
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/hero-contact.component.ts','component','app/hero-contact.component.ts')
|
||||
:marked
|
||||
|
@ -573,7 +573,7 @@ figure.image-display
|
|||
Although we strive to avoid it, many visual effects and 3rd party tools (such as jQuery)
|
||||
require DOM access.
|
||||
|
||||
偶尔,我们可能需要访问一个组件对应的DOM元素。我们尽量避免这样做,但还是有很多视觉效果和第三方工具(比如jQuery)需要访问DOM。
|
||||
偶尔,我们可能需要访问一个组件对应的DOM元素。我们尽量避免这样做,但还是有很多视觉效果和第三方工具(比如jQuery)需要访问DOM。
|
||||
|
||||
To illustrate, we've written a simplified version of the `HighlightDirective` from
|
||||
the [Attribute Directives](../guide/attribute-directives.html) chapter.
|
||||
|
@ -722,7 +722,7 @@ a(id='provide')
|
|||
The *definition* object has one main property, (e.g. `useValue`) that indicates how the provider
|
||||
should create or return the provided value.
|
||||
|
||||
该*定义*对象有一个主属性(即`userValue`),用来标识该供应商会如何新建和返回依赖。
|
||||
该*定义*对象有一个主属性(即`userValue`),用来标识该供应商会如何新建和返回依赖。
|
||||
|
||||
.l-main-section
|
||||
a(id='usevalue')
|
||||
|
@ -739,7 +739,7 @@ a(id='usevalue')
|
|||
We often use a *value provider* in a unit test to replace a production service with a fake or mock.
|
||||
|
||||
使用该技巧来进行*运行期常量设置*,比如网站的基础地址和功能标志等。
|
||||
我们通常在单元测试中使用*值-供应商*,用一个假的或模仿的(服务)来取代一个生产环境的服务。
|
||||
我们通常在单元测试中使用*值-供应商*,用一个假的或模仿的(服务)来取代一个生产环境的服务。
|
||||
|
||||
The `HeroOfTheMonthComponent` example has two *value providers*.
|
||||
The first provides an instance of the `Hero` class;
|
||||
|
@ -938,7 +938,7 @@ a(id="tokens")
|
|||
Angular dependency injection is easiest when the provider *token* is a class
|
||||
that is also the type of the returned dependency object (what we usually call the *service*).
|
||||
|
||||
Angular依赖注入当*令牌*是类的时候是最简单的,该类同时也是返回的依赖对象的类型(我们通常直接称之为*服务*)。
|
||||
Angular依赖注入当*令牌*是类的时候是最简单的,该类同时也是返回的依赖对象的类型(我们通常直接称之为*服务*)。
|
||||
|
||||
But the token doesn't have to be a class and even when it is a class,
|
||||
it doesn't have to be the same type as the returned object.
|
||||
|
@ -977,7 +977,7 @@ a(id="tokens")
|
|||
`DateLoggerService` inherits (extends) from `LoggerService`, not `MinimalLogger`.
|
||||
The `DateLoggerService` *implements* `MinimalLogger` as if `MinimalLogger` were an *interface*.
|
||||
|
||||
`DateLoggerService`继承(扩展)了`LoggerService`,而不是`MinimalLogger`。该`DateLoggerService`*实现了*`MinimalLogger`,就像`MinimalLogger`是一个接口一样。
|
||||
`DateLoggerService`继承(扩展)了`LoggerService`,而不是`MinimalLogger`。该`DateLoggerService`*实现了*`MinimalLogger`,就像`MinimalLogger`是一个接口一样。
|
||||
|
||||
We call a class used in this way a ***class-interface***.
|
||||
The key benefit of a *class-interface* is that we can get the strong-typing of an interface
|
||||
|
@ -1094,7 +1094,7 @@ figure.image-display
|
|||
This rule makes the component safe to construct under test without fear that it will do something dramatic like talk to the server.
|
||||
That's why we call the `HeroService` from within the `ngOnInit` rather than the constructor.
|
||||
|
||||
我们强烈推荐简单的构造函数。它们应该***只***用来初始化变量。这个规则会帮助我们在测试环境中放心的构造组件,以免在构造它们时,无意做了一些非常戏剧化的动作(比如连接服务)。
|
||||
我们强烈推荐简单的构造函数。它们应该***只***用来初始化变量。这个规则会帮助我们在测试环境中放心的构造组件,以免在构造它们时,无意做了一些非常戏剧化的动作(比如连接服务)。
|
||||
这就是为什么我们要在`ngOnInit`里面调用`HeroService`,而不是在构造函数中。
|
||||
|
||||
We explain the mysterious `afterGetHeroes` below.
|
||||
|
@ -1109,7 +1109,7 @@ figure.image-display
|
|||
(we said it was contrived).
|
||||
|
||||
用户希望看到英雄按字母顺序排序。与其修改原始的组件,不如派生它,新建`SortedHeroesComponent`,以便展示英雄之前进行排序。
|
||||
`SortedHeroesComponent`让基类来获取英雄。(我们说过这是生造的,仅用来解释这种机制)。
|
||||
`SortedHeroesComponent`让基类来获取英雄。(我们说过这是生造的,仅用来解释这种机制)。
|
||||
|
||||
Unfortunately, Angular cannot inject the `HeroService` directly into the base class.
|
||||
We must provide the `HeroService` again for *this* component,
|
||||
|
@ -1160,7 +1160,7 @@ a(id="find-parent")
|
|||
There is an API for acquiring a child reference
|
||||
(checkout `Query`, `QueryList`, `ViewChildren`, and `ContentChildren`).
|
||||
|
||||
有一个API可以获取子级的引用(请看`Query`, `QueryList`, `ViewChildren`,和`ContentChildren`)。
|
||||
有一个API可以获取子级的引用(请看`Query`, `QueryList`, `ViewChildren`,和`ContentChildren`)。
|
||||
|
||||
There is no public API for acquiring a parent reference.
|
||||
But because every component instance is added to an injector's container,
|
||||
|
@ -1216,7 +1216,7 @@ a(id='alex')
|
|||
For sound (cough) business reasons, this news component makes frequent calls
|
||||
directly into its parent instrument as changing market data stream by.
|
||||
|
||||
一个可复用的组件可能是多个组件的子级。想象一个用来渲染金融工具头条新闻的组件。为了合理(咳咳)的商业理由,该新闻组件在实时变化的市场数据流过时,要频繁的直接调用其父级工具。
|
||||
一个可复用的组件可能是多个组件的子级。想象一个用来渲染金融工具头条新闻的组件。为了合理(咳咳)的商业理由,该新闻组件在实时变化的市场数据流过时,要频繁的直接调用其父级工具。
|
||||
|
||||
The app probably defines more than a dozen financial instrument components.
|
||||
If we're lucky, they all implement the same base class
|
||||
|
@ -1241,7 +1241,7 @@ a(id='alex')
|
|||
The sample's `CraigComponent` explores this question. [Looking back](#alex)
|
||||
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
|
||||
|
||||
`CraigComponent`例子探究了这个问题。[往回看Alex]{#alex},我们看到`Alex`组件*扩展*(*派生*)自一个叫`Base`的类。
|
||||
`CraigComponent`例子探究了这个问题。[往回看Alex]{#alex},我们看到`Alex`组件*扩展*(*派生*)自一个叫`Base`的类。
|
||||
|
||||
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-class-signature','parent-finder.component.ts (Alex class signature)')(format='.')
|
||||
:marked
|
||||
|
@ -1331,7 +1331,7 @@ a(id="parent-tree")
|
|||
*Barry*'s `providers` array looks just like [*Alex*'s](#alex-providers).
|
||||
If we're going to keep writing [*alias providers*](#useexisting) like this we should create a [helper function](#provideparent).
|
||||
|
||||
*Barry*的`providers`数组看起来很像[*Alex*的那个](#alex-providers).
|
||||
*Barry*的`providers`数组看起来很像[*Alex*的那个](#alex-providers).
|
||||
如果我们准备一直像这样编写[*别名供应商*](#useexisting)的话,我们应该建立一个[帮助函数](#provideparent)。
|
||||
|
||||
For now, focus on *Barry*'s constructor:
|
||||
|
|
|
@ -48,7 +48,7 @@ code-example(format='')
|
|||
inside a Web Worker to improve your app's responsiveness by using multiple threads. And it
|
||||
means that you could run your app inside Electron.js or Windows Universal to deliver it to the desktop.
|
||||
|
||||
在浏览器外运行应用程序意味着:利用服务器端预先渲染,为应用程序实现几乎实时的首次渲染,同时还能支持SEO(搜索引擎优化)。
|
||||
在浏览器外运行应用程序意味着:利用服务器端预先渲染,为应用程序实现几乎实时的首次渲染,同时还能支持SEO(搜索引擎优化)。
|
||||
意味着你可以在一个Web Worker中运行你的应用程序,通过多线程技术增强应用程序的响应性。
|
||||
还意味着你可以在Electron.js或者Windows Universal里面运行,发布到桌面环境。
|
||||
|
||||
|
@ -103,7 +103,7 @@ figure.image-display
|
|||
:marked
|
||||
Here's the complete solution
|
||||
|
||||
这里是完整的方案(代码)。
|
||||
这里是完整的方案(代码)。
|
||||
|
||||
+makeTabs(
|
||||
`cb-set-document-title/ts/app/main.ts,
|
||||
|
|
|
@ -28,17 +28,17 @@ include _util-fns
|
|||
.l-main-section
|
||||
:marked
|
||||
## Annotation
|
||||
## 注解(Annotation)
|
||||
## 注解(Annotation)
|
||||
.l-sub-section
|
||||
:marked
|
||||
In practice a synonym for [Decoration](#decorator).
|
||||
|
||||
[装饰器(Decoration)](#decorator)在实践中的同义词。
|
||||
[装饰器(Decoration)](#decorator)在实践中的同义词。
|
||||
// #enddocregion a-1
|
||||
// #docregion a-2
|
||||
:marked
|
||||
## Attribute Directive
|
||||
## 属性型指令(Attribute Directive)
|
||||
## 属性型指令(Attribute Directive)
|
||||
.l-sub-section
|
||||
:marked
|
||||
A category of [Directive](#directive) that can listen to and modify the behavior of
|
||||
|
@ -61,7 +61,7 @@ include _util-fns
|
|||
.l-main-section
|
||||
:marked
|
||||
## Barrel
|
||||
## 封装桶(Barrel)
|
||||
## 封装桶(Barrel)
|
||||
.l-sub-section
|
||||
:marked
|
||||
A barrel is a way to *rollup exports* from several modules into a single convenience module.
|
||||
|
@ -93,7 +93,7 @@ include _util-fns
|
|||
:marked
|
||||
We can add a barrel to the `heroes` folder (called `index` by convention) that exports all of these items:
|
||||
|
||||
我们可以在`heroes`目录下添加一个封装桶(按规约叫做`index`),它导出所有这三条:
|
||||
我们可以在`heroes`目录下添加一个封装桶(按规约叫做`index`),它导出所有这三条:
|
||||
code-example(format='').
|
||||
export * from './hero.model.ts'; // re-export all of its exports
|
||||
export * from './hero.service.ts'; // re-export all of its exports
|
||||
|
@ -169,8 +169,8 @@ include _util-fns
|
|||
This form is also known as **lower camel case**, to distinguish it from **upper camel case** which we call [PascalCase](#pascalcase).
|
||||
When we write "camelCase" in this documentation we always mean *lower camel case*.
|
||||
|
||||
这种形式也被叫做**小驼峰式命名法(lower camel case)**,以区分于**大驼峰式命名法**(我们也叫[Pascal命名法(PascalCase)](#pascalcase))。
|
||||
当我们在文档中提到“驼峰式命名法(camelCase)”的时候,所指的都是小驼峰命名法。
|
||||
这种形式也被叫做**小驼峰式命名法(lower camel case)**,以区分于**大驼峰式命名法**(我们也叫[Pascal命名法(PascalCase)](#pascalcase))。
|
||||
当我们在文档中提到“驼峰式命名法(camelCase)”的时候,所指的都是小驼峰命名法。
|
||||
|
||||
:marked
|
||||
## Component
|
||||
|
@ -231,7 +231,7 @@ include _util-fns
|
|||
Applications display data values to a user and respond to user
|
||||
actions (clicks, touches, keystrokes).
|
||||
|
||||
应用程序会将数据展示给用户,并对用户的操作(点击、触屏、按键)做出回应。
|
||||
应用程序会将数据展示给用户,并对用户的操作(点击、触屏、按键)做出回应。
|
||||
|
||||
We could push application data values into HTML, attach
|
||||
event listeners, pull changed values from the screen, and
|
||||
|
@ -254,19 +254,19 @@ include _util-fns
|
|||
The many forms of binding include:
|
||||
绑定形式包括:
|
||||
* [Interpolation](/docs/ts/latest/guide/template-syntax.html#interpolation)
|
||||
* [插值表达式(Interpolation)](/docs/ts/latest/guide/template-syntax.html#interpolation)
|
||||
* [插值表达式(Interpolation)](/docs/ts/latest/guide/template-syntax.html#interpolation)
|
||||
* [Property Binding](/docs/ts/latest/guide/template-syntax.html#property-binding)
|
||||
* [属性绑定(Property Binding)](/docs/ts/latest/guide/template-syntax.html#property-binding)
|
||||
* [属性绑定(Property Binding)](/docs/ts/latest/guide/template-syntax.html#property-binding)
|
||||
* [Event Binding](/docs/ts/latest/guide/template-syntax.html#event-binding)
|
||||
* [事件绑定(Event Binding)](/docs/ts/latest/guide/template-syntax.html#event-binding)
|
||||
* [事件绑定(Event Binding)](/docs/ts/latest/guide/template-syntax.html#event-binding)
|
||||
* [Attribute Binding](/docs/ts/latest/guide/template-syntax.html#attribute-binding)
|
||||
* [Attribute绑定(Attribute Binding)](/docs/ts/latest/guide/template-syntax.html#attribute-binding)
|
||||
* [Attribute绑定(Attribute Binding)](/docs/ts/latest/guide/template-syntax.html#attribute-binding)
|
||||
* [Class Binding](/docs/ts/latest/guide/template-syntax.html#class-binding)
|
||||
* [CSS类绑定(Class Binding)](/docs/ts/latest/guide/template-syntax.html#class-binding)
|
||||
* [CSS类绑定(Class Binding)](/docs/ts/latest/guide/template-syntax.html#class-binding)
|
||||
* [Style Binding](/docs/ts/latest/guide/template-syntax.html#style-binding)
|
||||
* [样式绑定(Style Binding)](/docs/ts/latest/guide/template-syntax.html#style-binding)
|
||||
* [样式绑定(Style Binding)](/docs/ts/latest/guide/template-syntax.html#style-binding)
|
||||
* [Two-way data binding with ngModel](/docs/ts/latest/guide/template-syntax.html#ng-model)
|
||||
* [基于ngModel的双向数据绑定(Two-way data binding with ngModel)](/docs/ts/latest/guide/template-syntax.html#ng-model)
|
||||
* [基于ngModel的双向数据绑定(Two-way data binding with ngModel)](/docs/ts/latest/guide/template-syntax.html#ng-model)
|
||||
|
||||
Learn more about data binding in the
|
||||
[Template Syntax](/docs/ts/latest/guide/template-syntax.html#data-binding) chapter.
|
||||
|
@ -282,11 +282,11 @@ include _util-fns
|
|||
:marked
|
||||
A Decorator is a **function** that adds metadata to a class, its members (properties, methods) and function arguments.
|
||||
|
||||
装饰器是一个**函数**,这个函数将元数据添加到类、类成员(属性、方法)和函数上。
|
||||
装饰器是一个**函数**,这个函数将元数据添加到类、类成员(属性、方法)和函数上。
|
||||
|
||||
Decorators are a JavaScript language [feature](https://github.com/wycats/javascript-decorators), implemented in TypeScript and proposed for ES2016 (AKA ES7).
|
||||
|
||||
装饰器是一个JavaScript的语言[特性](https://github.com/wycats/javascript-decorators),装饰器在TypeScript里面已经采纳并实现了,并被推荐到了ES2016(也就是ES7)。
|
||||
装饰器是一个JavaScript的语言[特性](https://github.com/wycats/javascript-decorators),装饰器在TypeScript里面已经采纳并实现了,并被推荐到了ES2016(也就是ES7)。
|
||||
|
||||
We apply a decorator by positioning it
|
||||
immediately above or to the left of the thing it decorates.
|
||||
|
@ -435,7 +435,7 @@ include _util-fns
|
|||
as if they were writing native HTML. In this way, directives become extensions of
|
||||
HTML itself.
|
||||
|
||||
开发人员可以为自定义指令指定自定义的HTML标签(比如`<my-directive>`),然后,他们就可以像写原生HTML一样把这些自定义标签放到HTML模板里了。
|
||||
开发人员可以为自定义指令指定自定义的HTML标签(比如`<my-directive>`),然后,他们就可以像写原生HTML一样把这些自定义标签放到HTML模板里了。
|
||||
这样,指令就变成了HTML本身的拓展。
|
||||
|
||||
Directives fall into one of three categories:
|
||||
|
@ -478,13 +478,13 @@ include _util-fns
|
|||
either in this version of the language or a dialect that strives to be
|
||||
compatible with it such as [TypeScript](#typesScript).
|
||||
|
||||
最新的被认可的JavaScript版本是[ECMAScript 2015](http://www.ecma-international.org/ecma-262/6.0/),(也叫“ES2015”或“ES6”)。Angular 2的开发者要么使用这个版本的JavaScript,要么使用与这个版本兼容的语言,比如[TypeScript](#typesScript)。
|
||||
最新的被认可的JavaScript版本是[ECMAScript 2015](http://www.ecma-international.org/ecma-262/6.0/),(也叫“ES2015”或“ES6”)。Angular 2的开发者要么使用这个版本的JavaScript,要么使用与这个版本兼容的语言,比如[TypeScript](#typesScript)。
|
||||
|
||||
Most modern browsers today only support the prior "ECMAScript 5" (AKA ES5) standard.
|
||||
Applications written in ES2015 or one of its dialects must be "[transpiled](#transpile)"
|
||||
to ES5 JavaScript.
|
||||
|
||||
目前,几乎所有现代游览器都只支持上一个版本的“ECMAScript 5” (也就是ES5)标准。使用ES2015或者其它兼容语言开发的应用程序,都必须被“[转译(Transpile)](#transpile)”成ES5 JavaScript。
|
||||
目前,几乎所有现代游览器都只支持上一个版本的“ECMAScript 5” (也就是ES5)标准。使用ES2015或者其它兼容语言开发的应用程序,都必须被“[转译(Transpile)](#transpile)”成ES5 JavaScript。
|
||||
|
||||
Angular 2 developers may choose to write in ES5 directly.
|
||||
|
||||
|
@ -589,7 +589,7 @@ include _util-fns
|
|||
:marked
|
||||
The practice of writing compound words or phrases such that each word is separated by a dash or hyphen (-).
|
||||
|
||||
使用中线(-)分隔每个单词来书写复合词或短语的命名方法。
|
||||
使用中线(-)分隔每个单词来书写复合词或短语的命名方法。
|
||||
|
||||
Directive selectors and the root of filenames are often spelled in kebab-case. Examples include: `my-app` and the `hero-list.component.ts`.
|
||||
|
||||
|
@ -724,7 +724,7 @@ include _util-fns
|
|||
in the template expression to the right of the equal sign.
|
||||
|
||||
输出属性是指令的一种属性,它可作为[事件绑定](/docs/ts/latest/guide/template-syntax.html#property-binding)的 **目标** 。
|
||||
事件流可以通过这个属性,流出到接收者(模板表达式等号的右边就是接收者)。
|
||||
事件流可以通过这个属性,流出到接收者(模板表达式等号的右边就是接收者)。
|
||||
|
||||
See the [Template Syntax](/docs/ts/latest/guide/template-syntax.html#inputs-outputs) chapter.
|
||||
|
||||
|
@ -781,7 +781,7 @@ include _util-fns
|
|||
A Provider creates a new instance of a dependency for the Dependency Injection system.
|
||||
It relates a lookup token to code - sometimes called a "recipe" - that can create a dependency value.
|
||||
|
||||
依赖注入系统依靠供应商来创建依赖的实例。它把一个供查阅用的令牌和代码(有时也叫“配方”)关联到一起,以便创建依赖值。
|
||||
依赖注入系统依靠供应商来创建依赖的实例。它把一个供查阅用的令牌和代码(有时也叫“配方”)关联到一起,以便创建依赖值。
|
||||
|
||||
For example, `new Provider(Foo, {useClass: Foo})` creates a `Provider`
|
||||
that relates the `Foo` token to a function that creates a new instance of the `Foo` class.
|
||||
|
@ -920,7 +920,7 @@ include _util-fns
|
|||
The process of transforming code written in one form of JavaScript
|
||||
(e.g., TypeScript) into another form of JavaScript (e.g., [ES5](#es5)).
|
||||
|
||||
把用JavaScript的某种形态(比如TypeScript)编写的程序转换成另一个形式的JavaScript(例如[ES5](#es5))的过程。
|
||||
把用JavaScript的某种形态(比如TypeScript)编写的程序转换成另一个形式的JavaScript(例如[ES5](#es5))的过程。
|
||||
:marked
|
||||
## TypeScript
|
||||
.l-sub-section
|
||||
|
@ -929,14 +929,14 @@ include _util-fns
|
|||
language features and many features that may arrive in future versions
|
||||
of JavaScript such as [Decorators](#decorator).
|
||||
|
||||
一种支持了几乎所有[ECMAScript 2015](#ecmascript=2015)语言特性和一些未来版本可能有的特性(比如[装饰器(Decorator)](#decorator))的JavaScript语言。
|
||||
一种支持了几乎所有[ECMAScript 2015](#ecmascript=2015)语言特性和一些未来版本可能有的特性(比如[装饰器(Decorator)](#decorator))的JavaScript语言。
|
||||
|
||||
TypeScript is also noteable for its optional typing system which gives
|
||||
us compile-time type-checking and strong tooling support (e.g. "intellisense",
|
||||
code completion, refactoring, and intelligent search). Many code editors
|
||||
and IDEs support TypeScript either natively or with plugins.
|
||||
|
||||
TypeScript同时也以它的可选类型系统著称。该类型系统给我们提供了编译期类型检查和强大的工具支持(比如“Intellisense”, 自动代码补齐,重构和智能搜索等)。许多程序编辑器和开发环境都自带了TypeScript支持或通过插件提供支持。
|
||||
TypeScript同时也以它的可选类型系统著称。该类型系统给我们提供了编译期类型检查和强大的工具支持(比如“Intellisense”, 自动代码补齐,重构和智能搜索等)。许多程序编辑器和开发环境都自带了TypeScript支持或通过插件提供支持。
|
||||
|
||||
TypeScript is the preferred language for Angular 2 development although
|
||||
we are welcome to write in other JavaScript dialects such as [ES5](#es5).
|
||||
|
@ -1002,7 +1002,7 @@ include _util-fns
|
|||
[XHR](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)
|
||||
calls to remote servers.
|
||||
|
||||
浏览器中的DOM和JavaScript之间常会有一些数量有限的异步活动,比如DOM事件(如点击)、[承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/
|
||||
浏览器中的DOM和JavaScript之间常会有一些数量有限的异步活动,比如DOM事件(如点击)、[承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/
|
||||
Promise)、和通过[XHR](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)查询远程服务等。
|
||||
|
||||
Zones intercept all of these activities and give a "zone client" the opportunity
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
"dependency-injection": {
|
||||
"title": "依赖注入",
|
||||
"intro": "Angular的依赖注入系统能够JIT(刚好及时)的创建和交付所依赖的服务。",
|
||||
"intro": "Angular的依赖注入系统能够JIT(刚好及时)的创建和交付所依赖的服务。",
|
||||
"nextable": true,
|
||||
"basics": true
|
||||
},
|
||||
|
|
|
@ -112,12 +112,12 @@ figure
|
|||
Each chapter has plenty to offer after you steer clear of the `import` and `export` statements.
|
||||
|
||||
Angular本身并不需要模块化方案,也不需要使用这种特定的语法。如果你不喜欢,可以不用它。
|
||||
就算你避开`import`和`export`语句,每章也会为你提供很多(知识)。
|
||||
就算你避开`import`和`export`语句,每章也会为你提供很多(知识)。
|
||||
|
||||
Find setup and organization clues in the JavaScript track (select it from the combo-box at the top of this page)
|
||||
which demonstrates Angular 2 development with plain old JavaScript and no module system.
|
||||
|
||||
在JavaScript(你可以从页面顶部的组合框选择JavaScript)分支下,可以找到如何安装和组织的线索。
|
||||
在JavaScript(你可以从页面顶部的组合框选择JavaScript)分支下,可以找到如何安装和组织的线索。
|
||||
它示范了如何用老版本的JavaScript语言,在没有模块化系统支持的情况下进行Angular 2应用程序的开发。
|
||||
:marked
|
||||
Perhaps the first module we meet is a module that exports a *component* class.
|
||||
|
@ -153,7 +153,7 @@ figure
|
|||
The **module name** (AKA module id) is often the same as the filename without its extension.
|
||||
|
||||
`import`语句告诉系统,它能从附近名叫`app.component`的文件中获得`AppComponent`组件。
|
||||
**模块名**(又叫模块ID)通常和去掉扩展名后的文件名相同。
|
||||
**模块名**(又叫模块ID)通常和去掉扩展名后的文件名相同。
|
||||
|
||||
### Library Modules
|
||||
### 模块库
|
||||
|
@ -171,7 +171,7 @@ figure
|
|||
|
||||
Angular本身就是通过npm包发布的一组模块库,它们都以`@angular`为前缀。
|
||||
每个Angular库中都包含一个[封装桶](../glossary.html#barrel)模块。
|
||||
它实际上是一个公开的外观层(façade),囊括了一些逻辑相关的私有模块。
|
||||
它实际上是一个公开的外观层(façade),囊括了一些逻辑相关的私有模块。
|
||||
|
||||
The `@angular/core` library is the primary Angular library module from which we get most of what we need.
|
||||
|
||||
|
@ -208,8 +208,8 @@ figure
|
|||
We could path up and around the application folder structure if the source module were somewhere else.
|
||||
|
||||
当我们从*自己的*文件中导入时,模块名中带有路径前缀。
|
||||
在这个例子中,前缀是一个相对路径(./)。这表示源模块和想导入它的模块位于同一个目录中(./)。
|
||||
如果源模块位于其它位置,我们还可以向上引用应用目录结构中的任意路径(如`../../../somewhere/`)。
|
||||
在这个例子中,前缀是一个相对路径(./)。这表示源模块和想导入它的模块位于同一个目录中(./)。
|
||||
如果源模块位于其它位置,我们还可以向上引用应用目录结构中的任意路径(如`../../../somewhere/`)。
|
||||
.l-sub-section
|
||||
:marked
|
||||
We import and export in the ECMAScript 2015 (ES2015) module syntax.
|
||||
|
@ -266,7 +266,7 @@ figure
|
|||
We define a Component's application logic - what it does to support the view - inside a class.
|
||||
The class interacts with the view through an API of properties and methods.
|
||||
|
||||
我们在类中定义组件的应用逻辑(它被用来为视图提供支持)。
|
||||
我们在类中定义组件的应用逻辑(它被用来为视图提供支持)。
|
||||
组件通过一些由属性和方法组成的API与视图交互。
|
||||
|
||||
<a id="component-code"></a>
|
||||
|
@ -313,7 +313,7 @@ figure
|
|||
We define a Component's view with its companion **template**. A template is a form of HTML
|
||||
that tells Angular how to render the Component.
|
||||
|
||||
我们通过组件的自带的**模板**来定义视图。模板以HTML形式存在,用来告诉Angular如何渲染组件(视图)。
|
||||
我们通过组件的自带的**模板**来定义视图。模板以HTML形式存在,用来告诉Angular如何渲染组件(视图)。
|
||||
|
||||
A template looks like regular HTML much of the time ... and then it gets a bit strange. Here is a
|
||||
template for our `HeroList` component.
|
||||
|
@ -350,7 +350,7 @@ figure
|
|||
The `HeroDetailComponent` is a **child** of the `HeroListComponent`.
|
||||
|
||||
`HeroDetailComponent`跟我们以前回顾过的`HeroListComponent`是*不同*的组件。
|
||||
`HeroDetailComponent`(未展示代码)用于展现一个特定英雄的情况,这个英雄是用户从`HeroListComponent`列表中选择的。
|
||||
`HeroDetailComponent`(未展示代码)用于展现一个特定英雄的情况,这个英雄是用户从`HeroListComponent`列表中选择的。
|
||||
`HeroDetailComponent`是`HeroListComponent`的*子组件*。
|
||||
|
||||
figure
|
||||
|
@ -406,7 +406,7 @@ figure
|
|||
Here we see the `@Component` decorator which (no surprise) identifies the class
|
||||
immediately below it as a Component class.
|
||||
|
||||
这里我们看到`@Component`装饰器(毫无悬念的)把紧随其后的类标记成了组件类。
|
||||
这里我们看到`@Component`装饰器(毫无悬念的)把紧随其后的类标记成了组件类。
|
||||
|
||||
A decorator is a function. Decorators often have a configuration parameter.
|
||||
The `@Component` decorator takes a required configuration object with the
|
||||
|
@ -424,7 +424,7 @@ figure
|
|||
If the template of the application shell (a Component) contained
|
||||
|
||||
* `selector` - 一个css选择器,它告诉Angular在*父级*HTML中寻找一个`<hero-list>`标签,然后创建该组件,并插入此标签中。
|
||||
比如,如果应用“壳”(组件)的模板包含如下代码:
|
||||
比如,如果应用“壳”(组件)的模板包含如下代码:
|
||||
|
||||
<div style="margin-left:30px">
|
||||
code-example(language="html").
|
||||
|
@ -612,12 +612,12 @@ figure
|
|||
:marked
|
||||
There are two *other* kinds of directives as well that we call "structural" and "attribute" directives.
|
||||
|
||||
有两种*其它*类型的指令,我们称之为“结构型”指令和“属性(attribute)型”指令。
|
||||
有两种*其它*类型的指令,我们称之为“结构型”指令和“属性(attribute)型”指令。
|
||||
|
||||
They tend to appear within an element tag like attributes,
|
||||
sometimes by name but more often as the target of an assignment or a binding.
|
||||
|
||||
它们往往像属性(attribute)一样出现在元素标签中,偶尔会以名字的形式出现(参见[一次性绑定](./template-syntax.html#one-time-initialization)),但多数时候还是作为赋值目标或绑定目标出现。
|
||||
它们往往像属性(attribute)一样出现在元素标签中,偶尔会以名字的形式出现(参见[一次性绑定](./template-syntax.html#one-time-initialization)),但多数时候还是作为赋值目标或绑定目标出现。
|
||||
|
||||
**Structural** directives alter layout by adding, removing, and replacing elements in DOM.
|
||||
|
||||
|
@ -651,15 +651,15 @@ figure
|
|||
It modifies the behavior of an existing element (typically an `<input>`)
|
||||
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
|
||||
(e.g. [ngSwitch](template-syntax.html#ngSwitch))
|
||||
or modify aspects of DOM elements and components
|
||||
(e.g. [ngStyle](template-syntax.html#ngStyle) and [ngClass](template-syntax.html#ngClass)).
|
||||
|
||||
Angular内置了一些其它指令,它们或者修改结构布局(如[ngSwitch](template-syntax.html#ngSwitch)),或者修改DOM元素和组件的各个方面
|
||||
(如[ngStyle](template-syntax.html#ngStyle)和[ngClass](template-syntax.html#ngClass))。
|
||||
Angular内置了一些其它指令,它们或者修改结构布局(如[ngSwitch](template-syntax.html#ngSwitch)),或者修改DOM元素和组件的各个方面
|
||||
(如[ngStyle](template-syntax.html#ngStyle)和[ngClass](template-syntax.html#ngClass))。
|
||||
|
||||
And of course we can write our own directives.
|
||||
|
||||
|
@ -750,7 +750,7 @@ figure
|
|||
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.
|
||||
|
||||
组件的任务就是提供用户体验,仅此而已。它介于视图(由模板渲染)和应用逻辑(通常包括“模型model”的观念)之间。
|
||||
组件的任务就是提供用户体验,仅此而已。它介于视图(由模板渲染)和应用逻辑(通常包括“模型model”的观念)之间。
|
||||
设计良好的组件为数据绑定提供属性和方法,把那些其他对它们不重要的事情都委托给服务。
|
||||
|
||||
Angular doesn't *enforce* these principles.
|
||||
|
@ -842,7 +842,7 @@ figure
|
|||
... in which case we get a new instance of the
|
||||
service with each new instance of that component.
|
||||
|
||||
... 在这种情况下,那个组件的每一个新实例都会有一个(在该组件注册的)服务的新实例。
|
||||
... 在这种情况下,那个组件的每一个新实例都会有一个(在该组件注册的)服务的新实例。
|
||||
|
||||
We've vastly over-simplified dependency injection for this overview.
|
||||
We can learn the full story in the [Dependency Injection](dependency-injection.html) chapter.
|
||||
|
@ -940,7 +940,7 @@ figure
|
|||
Most of them are covered in this Developers Guide (or soon will be):
|
||||
|
||||
这里是一个简短的、按字母排序的列表,列出了其它重要的Angular特性和服务。
|
||||
它们大多数已经(或即将)包括在这个《开发指南》中:
|
||||
它们大多数已经(或即将)包括在这个《开发指南》中:
|
||||
|
||||
>**Animations** - A forthcoming animation library makes it easy for developers to animate component behavior
|
||||
without deep knowledge of animation techniques or css.
|
||||
|
|
|
@ -76,7 +76,7 @@ p 试用#[+liveExampleLink2("在线例子")]。
|
|||
Besides, we're not just *setting* the color; we'll be *changing* the color
|
||||
in response to a user action, a mouse hover.
|
||||
|
||||
再说,我们不仅要*设置*颜色,还要响应用户的动作(鼠标悬浮),来*更改*这个颜色。
|
||||
再说,我们不仅要*设置*颜色,还要响应用户的动作(鼠标悬浮),来*更改*这个颜色。
|
||||
|
||||
.l-main-section
|
||||
a#write-directive
|
||||
|
@ -570,12 +570,12 @@ a#why-input
|
|||
A property is a *source* if it appears in the template expression to the ***right*** of the equals (=).
|
||||
|
||||
在以前的所有绑定中,指令或组件的属性都是绑定***源***。
|
||||
如果属性出现在了模板表达式等号(=)的***右侧***,它就是一个*源*。
|
||||
如果属性出现在了模板表达式等号(=)的***右侧***,它就是一个*源*。
|
||||
|
||||
A property is a *target* when it appears in **square brackets** ([ ]) to the **left** of the equals (=) ...
|
||||
as it is does when we bind to the `myHighlight` property of the `HighlightDirective`,
|
||||
|
||||
如果它出现在了**方括号**([ ])中,并且出现在等号(=)的**左侧**,它就是一个*目标*……
|
||||
如果它出现在了**方括号**([ ])中,并且出现在等号(=)的**左侧**,它就是一个*目标*……
|
||||
就像在我们绑定到`HighlightDirective`的`myHighlight`属性时所做的那样。
|
||||
+makeExample('attribute-directives/ts/app/app.component.html','pHost')(format=".")
|
||||
:marked
|
||||
|
@ -609,7 +609,7 @@ a#why-input
|
|||
Not just the one or two properties we expected them to target. *Every* property.
|
||||
That could really mess up our directive in ways we didn't anticipate and have no desire to support.
|
||||
|
||||
出乎意料的是,有些人(可能因为太天真)开始绑定到这个指令中的*每一个*属性。
|
||||
出乎意料的是,有些人(可能因为太天真)开始绑定到这个指令中的*每一个*属性。
|
||||
不仅仅是我们期望被作为目标使用的那一两个属性,而是*每一个*。
|
||||
这可能会扰乱指令的工作方式 —— 我们既不想这样做也不想支持他们这样做。
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"bold": [
|
||||
"(click)"
|
||||
],
|
||||
"description": "<p>当按钮(及其子元素)上的click事件被触发时,调用<code>readRainbow</code>方法,并把事件对象作为参数传入。</p>\n"
|
||||
"description": "<p>当按钮(及其子元素)上的click事件被触发时,调用<code>readRainbow</code>方法,并把事件对象作为参数传入。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "<div title=\"Hello {{ponyName}}\">",
|
||||
|
@ -312,14 +312,14 @@
|
|||
"bold": [
|
||||
"@HostBinding('[class.valid]')"
|
||||
],
|
||||
"description": "<p>把宿主元素的属性(比如CSS类:valid)绑定到指令/组件的属性(比如:isValid)。</p>\n"
|
||||
"description": "<p>把宿主元素的属性(比如CSS类:valid)绑定到指令/组件的属性(比如:isValid)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "@HostListener('click', ['$event']) onClick(e) {...}",
|
||||
"bold": [
|
||||
"@HostListener('click', ['$event'])"
|
||||
],
|
||||
"description": "<p>通过指令/组件的方法(例如onClick)订阅宿主元素的事件(例如click),可选传入一个参数($event)。</p>\n"
|
||||
"description": "<p>通过指令/组件的方法(例如onClick)订阅宿主元素的事件(例如click),可选传入一个参数($event)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "@ContentChild(myPredicate) myChildComponent;",
|
||||
|
@ -483,42 +483,42 @@
|
|||
"bold": [
|
||||
"@CanActivate"
|
||||
],
|
||||
"description": "<p>用函数定义的一个组件装饰器,路由器会先调用它来检测是否应该激活该组件。应该返回布尔值或承诺(Promise)。</p>\n"
|
||||
"description": "<p>用函数定义的一个组件装饰器,路由器会先调用它来检测是否应该激活该组件。应该返回布尔值或承诺(Promise)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "routerOnActivate(nextInstruction, prevInstruction) { ... }",
|
||||
"bold": [
|
||||
"routerOnActivate"
|
||||
],
|
||||
"description": "<p>导航到一个组件之后,路由器调用该组件的routerOnActivate方法(如已定义)。</p>\n"
|
||||
"description": "<p>导航到一个组件之后,路由器调用该组件的routerOnActivate方法(如已定义)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "routerCanReuse(nextInstruction, prevInstruction) { ... }",
|
||||
"bold": [
|
||||
"routerCanReuse"
|
||||
],
|
||||
"description": "<p>路由器调用组件的routerCanReuse方法(如已定义)来检测是复用本实例还是销毁它并创建一个新的。应该返回布尔值或承诺(Promise)。</p>\n"
|
||||
"description": "<p>路由器调用组件的routerCanReuse方法(如已定义)来检测是复用本实例还是销毁它并创建一个新的。应该返回布尔值或承诺(Promise)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "routerOnReuse(nextInstruction, prevInstruction) { ... }",
|
||||
"bold": [
|
||||
"routerOnReuse"
|
||||
],
|
||||
"description": "<p>当路由器发现可以复用一个组件实例时,它调用组件的routerOnReuse方法(如已定义)。</p>\n"
|
||||
"description": "<p>当路由器发现可以复用一个组件实例时,它调用组件的routerOnReuse方法(如已定义)。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "routerCanDeactivate(nextInstruction, prevInstruction) { ... }",
|
||||
"bold": [
|
||||
"routerCanDeactivate"
|
||||
],
|
||||
"description": "<p>路由器会调用如果要完成导航就得移除的每个组件的routerCanDeactivate方法(如已定义)。当且仅当所有的该方法都返回true或者承诺(Promise)被解决时,导航才会继续。</p>\n"
|
||||
"description": "<p>路由器会调用如果要完成导航就得移除的每个组件的routerCanDeactivate方法(如已定义)。当且仅当所有的该方法都返回true或者承诺(Promise)被解决时,导航才会继续。</p>\n"
|
||||
},
|
||||
{
|
||||
"syntax": "routerOnDeactivate(nextInstruction, prevInstruction) { ... }",
|
||||
"bold": [
|
||||
"routerOnDeactivate"
|
||||
],
|
||||
"description": "<p>在每个指令因为路由变更而被移除之前调用。可以返回一个承诺,来阻止移除本指令 —— 直到承诺(Promise)被解决。</p>\n"
|
||||
"description": "<p>在每个指令因为路由变更而被移除之前调用。可以返回一个承诺,来阻止移除本指令 —— 直到承诺(Promise)被解决。</p>\n"
|
||||
}
|
||||
],
|
||||
"index": 10
|
||||
|
|
|
@ -115,7 +115,7 @@ a(id="special-selectors")
|
|||
Use the `:host` pseudo-class selector to target styles in the element that *hosts* the component (as opposed to
|
||||
targeting elements *inside* the component's template):
|
||||
|
||||
使用`:host`伪类选择器,用来选择组件*宿主*元素中的元素(相对于组件模板*内部*的元素)。
|
||||
使用`:host`伪类选择器,用来选择组件*宿主*元素中的元素(相对于组件模板*内部*的元素)。
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-details.component.css', 'host')(format='.')
|
||||
|
||||
|
@ -146,7 +146,7 @@ a(id="special-selectors")
|
|||
we want to change how our component looks based on that.
|
||||
|
||||
有时候,基于某些来自组件视图*外部*的条件应用样式是很有用的。
|
||||
比如,在文档的`<body>`元素上可能有一个用于表示样式主题(Theme)的CSS类,而我们应当基于它来决定组件的样式。
|
||||
比如,在文档的`<body>`元素上可能有一个用于表示样式主题(Theme)的CSS类,而我们应当基于它来决定组件的样式。
|
||||
|
||||
Use the `:host-context()` pseudo-class selector. It works just like the function
|
||||
form of `:host()`. It looks for a CSS class in *any ancestor* of the component host element, all the way
|
||||
|
@ -224,7 +224,7 @@ a(id='loading-styles')
|
|||
Each string in the #{_array} (usually just one string) defines the CSS.
|
||||
|
||||
我们可以给`@Component`#{_decoratorCn}添加一个`styles`数组型属性。
|
||||
这个数组中的每一个字符串(通常也只有一个)定义一份CSS。
|
||||
这个数组中的每一个字符串(通常也只有一个)定义一份CSS。
|
||||
|
||||
+makeExample('component-styles/ts/app/hero-app.component.ts')
|
||||
|
||||
|
@ -349,8 +349,8 @@ a#view-encapsulation
|
|||
(and renaming) the CSS code to effectively scope the CSS to the component's view.
|
||||
See [Appendix 1](#inspect-generated-css) for details.
|
||||
|
||||
* `Emulated`模式(**默认值**)通过预处理(并改名)CSS代码来仿真Shadow DOM的行为,以达到把CSS样式局限在组件视图中的目的。
|
||||
参见[附录1](#inspect-generated-css)了解详情。(译注:只进不出,全局样式能进来,组件样式出不去)
|
||||
* `Emulated`模式(**默认值**)通过预处理(并改名)CSS代码来仿真Shadow DOM的行为,以达到把CSS样式局限在组件视图中的目的。
|
||||
参见[附录1](#inspect-generated-css)了解详情。(译注:只进不出,全局样式能进来,组件样式出不去)
|
||||
|
||||
* `None` means that Angular does no view encapsulation.
|
||||
Angular adds the CSS to the global styles.
|
||||
|
@ -358,7 +358,7 @@ a#view-encapsulation
|
|||
This is essentially the same as pasting the component's styles into the HTML.
|
||||
* `None`意味着Angular不使用视图包装。
|
||||
Angular会把CSS添加到全局样式中。而不会应用上前面讨论过的那些局限化规则、隔离和保护等规则。
|
||||
从本质上来说,这跟把组件的样式直接放进HTML是一样的。(译注:能进能出。)
|
||||
从本质上来说,这跟把组件的样式直接放进HTML是一样的。(译注:能进能出。)
|
||||
|
||||
Set the components encapsulation mode using the `encapsulation` property in the component metadata:
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ block ctor-syntax
|
|||
|
||||
We could write a giant class to do that:
|
||||
|
||||
我们可以写一个巨型类来做这件事(不好的模式):
|
||||
我们可以写一个巨型类来做这件事(不好的模式):
|
||||
|
||||
+makeExample('dependency-injection/ts/app/car/car-factory.ts', null, 'app/car/car-factory.ts')
|
||||
|
||||
|
@ -375,7 +375,7 @@ block ctor-syntax
|
|||
|
||||
我们甚至没有假装这是一个真实的服务。
|
||||
如果我们真的从一个远端服务器获取数据,这个API必须是异步的,可能得返回
|
||||
[ES2015 承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
||||
[ES2015 承诺(Promise)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
||||
我们也需要被迫重新处理组件如何消费该服务的方式。通常这个很重要,但是我们目前的故事不需要。
|
||||
|
||||
:marked
|
||||
|
@ -495,7 +495,7 @@ block ctor-syntax
|
|||
has `providers` information for `HeroService`.
|
||||
|
||||
注意构造函数参数有类型`HeroService`,并且`HeroListComponent`类有一个`@Component`装饰器
|
||||
(往上翻可以确认)。另外,记得父级组件(`HeroesComponent`)有`HeroService`的`providers`信息。
|
||||
(往上翻可以确认)。另外,记得父级组件(`HeroesComponent`)有`HeroService`的`providers`信息。
|
||||
|
||||
The constructor parameter type, the `@Component` #{_decorator},
|
||||
and the parent's `providers` information combine to tell the
|
||||
|
@ -658,7 +658,7 @@ block injectable-not-always-needed-in-ts
|
|||
fact `InjectableMetadata` #{_decorator}s that
|
||||
identify a class as a target for instantiation by an injector.
|
||||
|
||||
如果真的想要这样做,我们*可以*添加它。但是这不是必须的,因为`HerosComponent`已经被`@Component`标识,这个装饰器类(像`@Directive`和`@Pipe`一样,我们一会儿将会学到)
|
||||
如果真的想要这样做,我们*可以*添加它。但是这不是必须的,因为`HerosComponent`已经被`@Component`标识,这个装饰器类(像`@Directive`和`@Pipe`一样,我们一会儿将会学到)
|
||||
是一个<a href="#{injMetaUrl}">InjectableMetadata</a>的子类型。实际上,`InjectableMetadata`装饰器标识着一个类是注入器实例化的目标。
|
||||
|
||||
|
||||
|
@ -730,7 +730,7 @@ block real-logger
|
|||
|
||||
code-example(format="nocode").
|
||||
EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
|
||||
(异常:Logger类没有供应商!(HeroListComponent -> HeroService -> Logger))
|
||||
(异常:Logger类没有供应商!(HeroListComponent -> HeroService -> Logger))
|
||||
|
||||
:marked
|
||||
That's Angular telling us that the dependency injector couldn't find the *provider* for the logger.
|
||||
|
@ -862,7 +862,7 @@ block dart-diff-const-metadata
|
|||
This logger gets the user from the injected `UserService`,
|
||||
which happens also to be injected at the application level.
|
||||
|
||||
也许一个`EvenBetterLogger`(更好的日志)可以在日志消息中显示用户名。
|
||||
也许一个`EvenBetterLogger`(更好的日志)可以在日志消息中显示用户名。
|
||||
这个日志服务从一个注入进来的`UserService`中取得用户,`UserService`通常也会在应用级被注入。
|
||||
|
||||
+makeExample('dependency-injection/ts/app/providers.component.ts','EvenBetterLogger')(format='.')
|
||||
|
@ -1125,7 +1125,7 @@ block dart-diff-const-metadata-ctor
|
|||
the address of a web API endpoint) but these configuration objects aren't always instances of a class.
|
||||
They can be object literals such as this one:
|
||||
|
||||
应用程序经常为很多很小的因素(比如应用程序的标题,或者一个网络API终点的地址)定义配置对象,但是这些配置对象不总是类的实例。
|
||||
应用程序经常为很多很小的因素(比如应用程序的标题,或者一个网络API终点的地址)定义配置对象,但是这些配置对象不总是类的实例。
|
||||
他们可能是对象,比如下面这个:
|
||||
|
||||
+makeExample('dependency-injection/ts/app/app.config.ts','config','app/app-config.ts (excerpt)')(format='.')
|
||||
|
@ -1180,7 +1180,7 @@ block what-should-we-use-as-token
|
|||
to define and use an !{opaquetoken}.
|
||||
The definition looks like this:
|
||||
|
||||
解决方案是定义和使用一个!{opaquetoken}(不透明的令牌)。定义方式类似于这样:
|
||||
解决方案是定义和使用一个!{opaquetoken}(不透明的令牌)。定义方式类似于这样:
|
||||
|
||||
+makeExample('dependency-injection/ts/app/app.config.ts','token')(format='.')
|
||||
|
||||
|
@ -1250,7 +1250,7 @@ block dart-map-alternative
|
|||
adding a parameter to a constructor.
|
||||
|
||||
在本章中,我们学习了Angular依赖注入的基础。
|
||||
我们可以注册很多种类的供应商,还知道了该如何通过添加构造函数的参数来请求一个被注入对象(比如服务)。
|
||||
我们可以注册很多种类的供应商,还知道了该如何通过添加构造函数的参数来请求一个被注入对象(比如服务)。
|
||||
|
||||
Angular dependency injection is more capable than we've described.
|
||||
We can learn more about its advanced features, beginning with its support for
|
||||
|
@ -1296,7 +1296,7 @@ block dart-map-alternative
|
|||
to retrieve a service (`ROUS`) that isn't registered with this or any ancestor injector.
|
||||
|
||||
`get`方法如果解析不出所请求的服务,它就会抛出一个异常。
|
||||
我们还可以带上第二个参数(如果服务没找到,就把它作为默认值返回)调用`get`,
|
||||
我们还可以带上第二个参数(如果服务没找到,就把它作为默认值返回)调用`get`,
|
||||
在该例子中,我们获取了一个服务(`ROUS`),它没有在这个注入器或它的任何祖先中注册过。
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
|
|
@ -132,7 +132,7 @@ include ../_quickstart_repo
|
|||
We're ready to see changes in a running app by firing up the npm script that both compiles and serves our applications
|
||||
while watching for changes.
|
||||
|
||||
通过运行npm脚本(它能编译并启动一个能监视文件变化的服务器),我们能看到运行中的应用发生的变化。
|
||||
通过运行npm脚本(它能编译并启动一个能监视文件变化的服务器),我们能看到运行中的应用发生的变化。
|
||||
code-example(format="").
|
||||
npm start
|
||||
:marked
|
||||
|
@ -241,13 +241,13 @@ figure.image-display
|
|||
it is an example of a [template input variable](./template-syntax.html#ngForMicrosyntax).
|
||||
|
||||
注意看`ngFor`双引号表达式中的`hero`。
|
||||
它是一个[模板输入变量](./template-syntax.html#ngForMicrosyntax)(译注:即ngFor模板中从外界输入的变量)。
|
||||
它是一个[模板输入变量](./template-syntax.html#ngForMicrosyntax)(译注:即ngFor模板中从外界输入的变量)。
|
||||
|
||||
Angular duplicates the `<li>` for each item in the list, setting the `hero` variable
|
||||
to the item (the hero) in the current iteration. Angular uses that variable as the
|
||||
context for the interpolation in the double curly braces.
|
||||
|
||||
Angular为列表中的每一个条目复制一个`<li>`元素。在每个迭代中,都会把`hero`变量设置为当前条目(此英雄)。
|
||||
Angular为列表中的每一个条目复制一个`<li>`元素。在每个迭代中,都会把`hero`变量设置为当前条目(此英雄)。
|
||||
Angular把`hero`变量作为双花括号插值表达式的上下文。
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
|
|
@ -72,7 +72,7 @@ include ../_util-fns
|
|||
:marked
|
||||
That's not the only way to create a form but it's the way we'll cover in this chapter.
|
||||
|
||||
这不是创建表单的唯一方式,但它是我们将在本章中使用的方式。(译注:Angular支持的另一种方式叫做模型驱动表单Model-Driven Forms)
|
||||
这不是创建表单的唯一方式,但它是我们将在本章中使用的方式。(译注:Angular支持的另一种方式叫做模型驱动表单Model-Driven Forms)
|
||||
|
||||
:marked
|
||||
We can build almost any form we need with an Angular template — login forms, contact forms ... pretty much any business forms.
|
||||
|
@ -169,7 +169,7 @@ figure.image-display
|
|||
|
||||
Create a new project folder (`angular2-forms`) and follow the steps in the [QuickStart](../quickstart.html).
|
||||
|
||||
创建一个新的项目文件夹(`angular2-forms`),并且完成[“快速起步”](../quickstart.html)中的步骤。
|
||||
创建一个新的项目文件夹(`angular2-forms`),并且完成[“快速起步”](../quickstart.html)中的步骤。
|
||||
|
||||
include ../_quickstart_repo
|
||||
:marked
|
||||
|
@ -188,7 +188,7 @@ include ../_quickstart_repo
|
|||
and one optional field (`alterEgo`).
|
||||
|
||||
最简单的模型就是一个“属性包”,用来存放应用中一件事物的事实。
|
||||
这里我们使用三个必备字段(`id`、`name`、`power`),和一个可选字段(`alterEgo`,译注:中文含义:第二人格,比如X战警中的Jean/黑凤凰)。
|
||||
这里我们使用三个必备字段(`id`、`name`、`power`),和一个可选字段(`alterEgo`,译注:中文含义:第二人格,比如X战警中的Jean/黑凤凰)。
|
||||
|
||||
Create a new file in the app folder called `hero.ts` and give it the following class definition:
|
||||
|
||||
|
@ -208,7 +208,7 @@ include ../_quickstart_repo
|
|||
|
||||
The `alterEgo` is optional and the constructor lets us omit it; note the (?) in `alterEgo?`.
|
||||
|
||||
`alterEgo`是可选的,构造函数允许我们省略它,注意`alterEgo?`中的问号(?)。
|
||||
`alterEgo`是可选的,构造函数允许我们省略它,注意`alterEgo?`中的问号(?)。
|
||||
|
||||
We can create a new hero like this:
|
||||
|
||||
|
@ -287,7 +287,7 @@ code-example(format="").
|
|||
We also like short files with a clear and obvious purpose like this one.
|
||||
|
||||
没有什么答案在所有场合都总是“正确”的。当内联模板足够短的时候,我们更喜欢用它。
|
||||
但大多数的表单模板都不短。普遍来讲,TypeScript和JavaScript文件不是写大型HTML的好地方(也不好读)。
|
||||
但大多数的表单模板都不短。普遍来讲,TypeScript和JavaScript文件不是写大型HTML的好地方(也不好读)。
|
||||
而且没有几个编辑器能对混写的HTML和代码提供足够的帮助。
|
||||
我们还是喜欢写成像这个一样清晰明确的短文件。
|
||||
|
||||
|
@ -331,7 +331,7 @@ code-example(format="").
|
|||
1. The `directives` array tells Angular that our template depends upon the `HeroFormComponent`
|
||||
which is itself a Directive (as are all Components).
|
||||
|
||||
1. `directives`数组告诉Angular,我们的模板依赖于`HeroFormComponent`组件,它本身也是一个指令(所有组件都是指令)。
|
||||
1. `directives`数组告诉Angular,我们的模板依赖于`HeroFormComponent`组件,它本身也是一个指令(所有组件都是指令)。
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -612,7 +612,7 @@ figure.image-display
|
|||
the event handling such as debounce or throttle the key strokes.
|
||||
|
||||
很高兴知道这些,但是这样现实吗?实践上我们几乎总是优先使用`[(ngModel)]`形式的双向绑定。
|
||||
只有当我们不得不在事件处理函数中做一些特别的事情(比如合并或限制按键频率)时,才需要拆分出独立的事件处理函数。
|
||||
只有当我们不得不在事件处理函数中做一些特别的事情(比如合并或限制按键频率)时,才需要拆分出独立的事件处理函数。
|
||||
|
||||
Learn more about `NgModel` and other template syntax in the
|
||||
[Template Syntax](./template-syntax.html) chapter.
|
||||
|
@ -670,7 +670,7 @@ figure.image-display
|
|||
|
||||
我们模板中的这个`ngControl`*属性*实际上被映射到了 [NgControlName](../api/common/index/NgControlName-directive.html)指令。
|
||||
虽然还有另一个叫`NgControl`的*抽象*指令,但和这个属性不是一回事。
|
||||
我们通常会忽略这点技术上的差异。为了更方便(尽管不正确),我们提起`NgControlName`时还是会把它叫做*NgControl*指令。
|
||||
我们通常会忽略这点技术上的差异。为了更方便(尽管不正确),我们提起`NgControlName`时还是会把它叫做*NgControl*指令。
|
||||
|
||||
While we're under the hood, we might as well note that the `ngModel` in the
|
||||
two-way binding syntax is now a property of the `NgControlName` directive.
|
||||
|
@ -894,7 +894,7 @@ figure.image-display
|
|||
|
||||
这种用户体验取决于开发人员的选择。有些人会希望任何时候都显示这条消息。
|
||||
如果忽略了`pristine`状态,我们就会只在值有效时隐藏此消息。
|
||||
如果往这个组件中传入一个全新(空白)的英雄,或者一个无效的英雄,我们将立刻看到错误信息 —— 虽然我们还啥都没做。
|
||||
如果往这个组件中传入一个全新(空白)的英雄,或者一个无效的英雄,我们将立刻看到错误信息 —— 虽然我们还啥都没做。
|
||||
|
||||
Some folks find that behavior disconcerting. They only want to see the message when the user makes an invalid change.
|
||||
Hiding the message while the control is "pristine" achieves that goal.
|
||||
|
@ -951,7 +951,7 @@ figure.image-display
|
|||
This time we see an error message! Why? We don't want that when we display a new (empty) hero.
|
||||
|
||||
输入一个名字,并再次点击*新增英雄*按钮。
|
||||
这次,我们看到了错误信息!为什么?当我们显示一个新(空白)的英雄时,我们不希望如此。
|
||||
这次,我们看到了错误信息!为什么?当我们显示一个新(空白)的英雄时,我们不希望如此。
|
||||
|
||||
Inspecting the element in the browser tools reveals that the *name* input box is no longer pristine.
|
||||
Replacing the hero *did not restore the pristine state* of the control.
|
||||
|
@ -1092,7 +1092,7 @@ figure.image-display
|
|||
:marked
|
||||
## Toggle two form regions (extra credit)
|
||||
|
||||
## 切换两个表单区域(额外的荣誉)
|
||||
## 切换两个表单区域(额外的荣誉)
|
||||
|
||||
Submitting the form isn't terribly dramatic at the moment.
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ block includes
|
|||
interesting and useful results.
|
||||
|
||||
Angular有一个多级依赖注入系统。
|
||||
实际上,应用程序中有一个与组件树平行的注入器树(译注:平行是指结构完全相同且一一对应)。
|
||||
实际上,应用程序中有一个与组件树平行的注入器树(译注:平行是指结构完全相同且一一对应)。
|
||||
我们可以在组件树中的任何级别上重新配置注入器,达到一些有趣和有用的效果。
|
||||
|
||||
In this chapter we explore these points and write some code.
|
||||
|
@ -58,7 +58,7 @@ p 试试#[+liveExampleLink2("在线例子")].
|
|||
But it is true that every component ***has an injector*** (even if it shares that injector with another component)
|
||||
and there may be many different injector instances operating at different levels of the component tree.
|
||||
|
||||
但是,每个组件都**有一个注入器**是真实的(就算它与其它组件共享注入器,也是*有注入器*),并且确实可能会有大量不同的注入器实例工作在组件树的不同级别。
|
||||
但是,每个组件都**有一个注入器**是真实的(就算它与其它组件共享注入器,也是*有注入器*),并且确实可能会有大量不同的注入器实例工作在组件树的不同级别。
|
||||
|
||||
It is useful to pretend that every component has its own injector.
|
||||
|
||||
|
@ -129,9 +129,9 @@ figure.image-display
|
|||
This child is the parent of another component (C) that defines its own provider for `Car`.
|
||||
|
||||
让我们回到“汽车(Car)”类的例子。
|
||||
假设“根注入器”(记为A)配置过`Car`、`Engine`和`Tires`的供应商。
|
||||
然后创建了一个子组件(B),它为`Car`和`Engine`类定义了自己的供应商。
|
||||
这个子组件(B)又有另一个子组件(C),(C)也为`Car`定义了自己的供应商。
|
||||
假设“根注入器”(记为A)配置过`Car`、`Engine`和`Tires`的供应商。
|
||||
然后创建了一个子组件(B),它为`Car`和`Engine`类定义了自己的供应商。
|
||||
这个子组件(B)又有另一个子组件(C),(C)也为`Car`定义了自己的供应商。
|
||||
|
||||
Behind the scenes each component sets up its own injector with one or more providers defined for that component itself.
|
||||
|
||||
|
@ -141,8 +141,8 @@ figure.image-display
|
|||
its injector produces an instance of `Car` resolved by injector (C) with an `Engine` resolved by injector (B) and
|
||||
`Tires` resolved by the root injector (A).
|
||||
|
||||
当我们在最底层的组件(C)中试图解析出一个`Car`的实例时,注入器(C)解析出的`Car`类的实例,
|
||||
该`Car`的实例带有一个`Engine`类的实例(由注入器(B)解析出)和一个`Tires`类的实例(由跟注入器(A)解析出)。
|
||||
当我们在最底层的组件(C)中试图解析出一个`Car`的实例时,注入器(C)解析出的`Car`类的实例,
|
||||
该`Car`的实例带有一个`Engine`类的实例(由注入器(B)解析出)和一个`Tires`类的实例(由跟注入器(A)解析出)。
|
||||
|
||||
figure.image-display
|
||||
img(src="/resources/images/devguide/dependency-injection/injector-tree.png" alt="injector tree" width="600")
|
||||
|
@ -277,7 +277,7 @@ figure.image-display
|
|||
scoped to that component instance and its child components.
|
||||
|
||||
但很明显,这个场景下我们不希望这样。我们希望每个组件都有它自己的`RestoreService`实例。
|
||||
在组件级别上定义(或重定义)一个供应商,将会为该组件创建一个新的服务实例。
|
||||
在组件级别上定义(或重定义)一个供应商,将会为该组件创建一个新的服务实例。
|
||||
我们已经为`HeroEditComponent`制造了一种“私有”`RestoreService`单例,它的作用范围被局限在了该组件的实例及其子组件中。
|
||||
|
||||
<!--
|
||||
|
|
|
@ -259,7 +259,7 @@ table(width="100%")
|
|||
after the first `ngOnChanges`.
|
||||
|
||||
在第一轮`ngOnChanges`完成之后调用。
|
||||
(译注:也就是说当每个输入属性的值都被触发了一次ngOnChanges之后才会调用ngOnInit,此时所有输入属性都已经有了正确的初始绑定值)
|
||||
(译注:也就是说当每个输入属性的值都被触发了一次ngOnChanges之后才会调用ngOnInit,此时所有输入属性都已经有了正确的初始绑定值)
|
||||
tr(style=top)
|
||||
td ngDoCheck
|
||||
td
|
||||
|
@ -757,7 +757,7 @@ figure.image-display
|
|||
[incorrect API documentation](../api/core/DoCheck-interface.html).
|
||||
|
||||
我们还看到,`ngOnChanges`方法的调用方式与[API文档](../api/core/index/DoCheck-interface.html)中是不一样的,这是因为API文档过时了。
|
||||
(译注:这是经过与官方开发组沟通得到的消息,由于代码快速迭代,因此API文档现在的更新不够及时,将来会进行一次系统的梳理和更正)
|
||||
(译注:这是经过与官方开发组沟通得到的消息,由于代码快速迭代,因此API文档现在的更新不够及时,将来会进行一次系统的梳理和更正)
|
||||
.l-main-section
|
||||
:marked
|
||||
## AfterView
|
||||
|
|
|
@ -4,7 +4,7 @@ include ../_util-fns
|
|||
Angular applications and Angular itself depend upon features and functionality provided by a variety of third-party packages (including Angular itself).
|
||||
These packages are maintained and installed with the Node Package Manager (<a href="https://docs.npmjs.com/" target="_blank">npm</a>).
|
||||
|
||||
Angular应用程序以及Angular本身都依赖于很多第三方包(包括Angular自己)提供的特性和功能。
|
||||
Angular应用程序以及Angular本身都依赖于很多第三方包(包括Angular自己)提供的特性和功能。
|
||||
这些包由Node包管理器(<a href="https://docs.npmjs.com/" target="_blank">npm</a>)负责安装和维护。
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -232,7 +232,7 @@ a(id="other")
|
|||
Learn about it in the [Http Client](server-communication.html#appendix-tour-of-heroes-in-memory-server) chapter.
|
||||
|
||||
***angular2-in-memory-web-api*** - 一个Angular的支持库,它能模拟一个远端服务器的Web API,而不需要依赖一个真实的服务器或发起真实的HTTP调用。
|
||||
对演示、文档范例和开发的早期阶段(那时候我们可能还没有服务器呢)非常有用。
|
||||
对演示、文档范例和开发的早期阶段(那时候我们可能还没有服务器呢)非常有用。
|
||||
请到[Http客户端](server-communication.html#appendix-tour-of-heroes-in-memory-server)一章中了解更多知识。
|
||||
|
||||
***bootstrap*** - [bootstrap](http://getbootstrap.com/) is a popular HTML and CSS framework for designing responsive web apps.
|
||||
|
|
|
@ -271,7 +271,7 @@ p.
|
|||
|
||||
:marked
|
||||
## Power Boost Calculator (extra-credit)
|
||||
## 能力倍增计算器(加分项)
|
||||
## 能力倍增计算器(加分项)
|
||||
|
||||
It's not much fun updating the template to test our custom pipe.
|
||||
We could upgrade the example to a "Power Boost Calculator" that combines
|
||||
|
@ -308,7 +308,7 @@ a#change-detection
|
|||
The component in our next example uses the default, aggressive change detection strategy to monitor and update
|
||||
its display of every hero in the `heroes` #{_array}. Here's the template:
|
||||
|
||||
我们下一个例子中的组件使用默认的、激进(昂贵)的变更检测策略来检测和更新`heroes`数组中的每个英雄。下面是它的模板:
|
||||
我们下一个例子中的组件使用默认的、激进(昂贵)的变更检测策略来检测和更新`heroes`数组中的每个英雄。下面是它的模板:
|
||||
|
||||
+makeExample('pipes/ts/app/flying-heroes.component.html', 'template-1', 'app/flying-heroes.component.html (v1)')(format='.')
|
||||
|
||||
|
@ -348,7 +348,7 @@ p.
|
|||
Every hero we add is a flying hero but none of them are displayed.
|
||||
|
||||
p.
|
||||
如果我们现在就运行这个例子,我们会看到一些古怪的行为(在#[+liveExampleLink('在线例子')]中试试)。
|
||||
如果我们现在就运行这个例子,我们会看到一些古怪的行为(在#[+liveExampleLink('在线例子')]中试试)。
|
||||
我们添加的每个英雄都会飞,但他们一个都没有显示出来。
|
||||
|
||||
:marked
|
||||
|
@ -462,7 +462,7 @@ block pure-change
|
|||
pipe execution and a view update.
|
||||
|
||||
这可能看起来是一种限制,但它保证了速度。
|
||||
对象引用的检查是非常快的(比递归的深检查要快得多),所以Angular可以快速的决定是否应该跳过管道执行和视图更新。
|
||||
对象引用的检查是非常快的(比递归的深检查要快得多),所以Angular可以快速的决定是否应该跳过管道执行和视图更新。
|
||||
|
||||
For this reason, we prefer a pure pipe if we can live with the change detection strategy.
|
||||
When we can't, we *may* turn to the impure pipe.
|
||||
|
@ -570,7 +570,7 @@ h3#async-pipe 非纯管道#[i AsyncPipe]
|
|||
(a potent source of memory leaks).
|
||||
|
||||
这个Async管道节省了组件的样板代码。
|
||||
组件不用订阅这个异步数据源,而且不用在被销毁时取消订阅(如果订阅了而忘了反订阅容易导致隐晦的内存泄露)。
|
||||
组件不用订阅这个异步数据源,而且不用在被销毁时取消订阅(如果订阅了而忘了反订阅容易导致隐晦的内存泄露)。
|
||||
|
||||
### An impure caching pipe
|
||||
### 一个非纯而且带缓存的管道
|
||||
|
@ -596,7 +596,7 @@ h3#async-pipe 非纯管道#[i AsyncPipe]
|
|||
|
||||
我们确实得小心点儿。所以这个管道只有当所请求的URL发生变化时才会向服务器发起请求。
|
||||
它会缓存这个请求的URL,并等待一个结果,当结果发回来时,就缓存它。
|
||||
以后每当Angular调用此管道时,它都会返回这个缓存的结果(当请求尚未返回时,此结果是空),只在必要时才会去联系服务器。
|
||||
以后每当Angular调用此管道时,它都会返回这个缓存的结果(当请求尚未返回时,此结果是空),只在必要时才会去联系服务器。
|
||||
|
||||
Here's the code, which uses the [Angular http](server-communication.html) facility
|
||||
to retrieve a `heroes.json` file:
|
||||
|
|
|
@ -140,7 +140,7 @@ block http-providers
|
|||
|
||||
We register HTTP providers in the bootstrap method by passing them in an array as the second parameter after the root component.
|
||||
|
||||
然后我们把这些HTTP服务供应商作为第二个参数传给bootstrap方法(第一个参数用来指定根组件),把它们注册进应用程序。
|
||||
然后我们把这些HTTP服务供应商作为第二个参数传给bootstrap方法(第一个参数用来指定根组件),把它们注册进应用程序。
|
||||
|
||||
### Why register in *bootstrap*?
|
||||
### 为什么在*bootstrap*中注册?
|
||||
|
@ -161,7 +161,7 @@ block http-providers
|
|||
This replacement service is called the [*in-memory web api*](#in-mem-web-api).
|
||||
|
||||
因为这是一个*范例程序*,它不会跟真实的服务器打交道。
|
||||
我们准备用一个伪造的供应商来重新配置(通常不可见的)`XhrBackend`服务。这个伪造的供应商会从一个内存存储区中获取和保存范例数据。
|
||||
我们准备用一个伪造的供应商来重新配置(通常不可见的)`XhrBackend`服务。这个伪造的供应商会从一个内存存储区中获取和保存范例数据。
|
||||
这个用于替换的服务称为[*内存Web API*](#in-mem-web-api)。
|
||||
|
||||
Such sleight-of-hand is something the root application component should *not* know about.
|
||||
|
@ -250,12 +250,12 @@ a#HeroListComponent
|
|||
(especially calling a remote server) is handled in a separate method.
|
||||
|
||||
这是一项*最佳实践*。
|
||||
当组件的构造函数足够简单,而且所有真实的工作(尤其是调用远端服务器)都在一个独立的方法中处理时,组件会更加容易测试和调试。
|
||||
当组件的构造函数足够简单,而且所有真实的工作(尤其是调用远端服务器)都在一个独立的方法中处理时,组件会更加容易测试和调试。
|
||||
block getheroes-and-addhero
|
||||
:marked
|
||||
The service's `getHeroes()` and `addHero()` methods return an `Observable` of hero data that the !{_Angular_Http} client fetched from the server.
|
||||
|
||||
服务的`getHeroes()`和`addHero()`方法返回一个英雄数据的可观察对象(`Observable`),这些数据是由!{_Angular_Http}从服务器上获取的。
|
||||
服务的`getHeroes()`和`addHero()`方法返回一个英雄数据的可观察对象(`Observable`),这些数据是由!{_Angular_Http}从服务器上获取的。
|
||||
|
||||
*Observables* are a big topic, beyond the scope of this chapter.
|
||||
But we need to know a little about them to appreciate what is going on here.
|
||||
|
@ -316,7 +316,7 @@ h2#fetch-data 通过#[b HeroService]获取数据
|
|||
Alternatively, we can (temporarily) target a JSON file by changing the endpoint URL:
|
||||
|
||||
一旦我们按附录中所描述的那样准备好了[内存Web API](in-mem-web-api),它*将*返回英雄列表。
|
||||
但目前,我们只能(临时性的)使用一个JSON文件来代替这个“内存Web API”。只要修改下服务器的URL就行了:
|
||||
但目前,我们只能(临时性的)使用一个JSON文件来代替这个“内存Web API”。只要修改下服务器的URL就行了:
|
||||
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json')(format=".")
|
||||
|
||||
block rxjs
|
||||
|
@ -535,7 +535,7 @@ block error-handling
|
|||
|
||||
我们在服务层使用了可观察对象的`catch`操作符。
|
||||
它接受一个以error对象为参数的错误处理函数。
|
||||
我们的服务处理器(`handleError`)把响应对象记录到控制台中,
|
||||
我们的服务处理器(`handleError`)把响应对象记录到控制台中,
|
||||
把错误转换成对用户友好的消息,并且通过`Observable.throw`来把这个消息放进一个新的、用于表示“失败”的可观察对象。
|
||||
|
||||
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'error-handling', 'app/toh/hero.service.ts (excerpt)')(format=".")
|
||||
|
@ -781,7 +781,7 @@ h2#cors 跨域请求:Wikipedia范例
|
|||
Some servers do not support CORS but do support an older, read-only alternative called [JSONP](https://en.wikipedia.org/wiki/JSONP).
|
||||
Wikipedia is one such server.
|
||||
|
||||
有些服务器不支持CORS,但支持一种老的、只读的(译注:即仅支持GET)替代协议,这就是[JSONP](https://en.wikipedia.org/wiki/JSONP)。
|
||||
有些服务器不支持CORS,但支持一种老的、只读的(译注:即仅支持GET)替代协议,这就是[JSONP](https://en.wikipedia.org/wiki/JSONP)。
|
||||
Wikipedia就是一个这样的服务器。
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -831,7 +831,7 @@ block wikipedia-jsonp+
|
|||
The value of the `search` key is the user-supplied search term to find in Wikipedia.
|
||||
The other three are the fixed values "opensearch", "json", and "JSONP_CALLBACK" respectively.
|
||||
|
||||
[Wikipedia 的 'opensearch' API](https://www.mediawiki.org/wiki/API:Opensearch)期待在所请求的URL中带四个查询参数(键/值对格式)。
|
||||
[Wikipedia 的 'opensearch' API](https://www.mediawiki.org/wiki/API:Opensearch)期待在所请求的URL中带四个查询参数(键/值对格式)。
|
||||
这些键(key)分别是`search`、`action`、`format`和`callback`。
|
||||
`search`的值是用户提供的用于在Wikipedia中查找的关键字。
|
||||
另外三个参数是固定值,分别是"opensearch"、"json"和"JSONP_CALLBACK"。
|
||||
|
@ -896,7 +896,7 @@ block wikipedia-jsonp+
|
|||
|
||||
`search(term)`方法委托我们的`WikipediaService`服务来完成实际操作。该服务返回的是一个字符串数组的可观察对象(`Observable<string[]`)。
|
||||
该组件的内部订阅了这个可观察对象,就像我们曾在`HeroListComponent`中所做的那样,
|
||||
我们把这个可观察对象作为结果传给模板(通过`items`属性),模板中`ngFor`上的[async(异步)管道](pipes.html#async-pipe)会对这个订阅进行处理。
|
||||
我们把这个可观察对象作为结果传给模板(通过`items`属性),模板中`ngFor`上的[async(异步)管道](pipes.html#async-pipe)会对这个订阅进行处理。
|
||||
.l-sub-section
|
||||
:marked
|
||||
We often use the [async pipe](pipes.html#async-pipe) in read-only components where the component has no need to interact with the data.
|
||||
|
@ -911,7 +911,7 @@ block wikipedia-jsonp+
|
|||
Our wikipedia search makes too many calls to the server.
|
||||
It is inefficient and potentially expensive on mobile devices with limited data plans.
|
||||
|
||||
我们这个Wikipedia搜索程序触发了过多的服务器调用(每次按键发一次)。
|
||||
我们这个Wikipedia搜索程序触发了过多的服务器调用(每次按键发一次)。
|
||||
这样效率很低,而且在流量受限的移动设备上会显得过于昂贵。
|
||||
|
||||
### 1. Wait for the user to stop typing
|
||||
|
@ -1134,7 +1134,7 @@ block redirect-to-web-api
|
|||
|
||||
p Here is the revised (and final) version of the #[code #[+adjExPath('app/main.ts')]] demonstrating these steps.
|
||||
|
||||
p 下面是修改过的(也是最终的)#[code #[+adjExPath('app/main.ts')]]版本,用于演示这些步骤。
|
||||
p 下面是修改过的(也是最终的)#[code #[+adjExPath('app/main.ts')]]版本,用于演示这些步骤。
|
||||
+makeExample('server-communication/ts/app/main.ts', 'final', 'app/main.ts (final)')(format=".")
|
||||
|
||||
p See the full source code in the #[+liveExampleLink2()].
|
||||
|
|
|
@ -190,7 +190,7 @@ figure.image-display
|
|||
our recommendation and consider a component called `heavy-loader` that
|
||||
***pretends*** to load a ton of data when initialized.
|
||||
|
||||
让我们在实践中看看这些变化。为了娱乐,我们设想在甲板上有个叫`heavy-loader`(重型起重机)的组件,它会***假装***在初始化时装载一吨数据。
|
||||
让我们在实践中看看这些变化。为了娱乐,我们设想在甲板上有个叫`heavy-loader`(重型起重机)的组件,它会***假装***在初始化时装载一吨数据。
|
||||
|
||||
We'll display two instances of the component. We toggle the visibility of the first one with CSS.
|
||||
We toggle the second into and out of the DOM with `ngIf`.
|
||||
|
@ -271,7 +271,7 @@ figure.image-display
|
|||
:marked
|
||||
The display is a 'Hip! Hooray!', short of perfect enthusiasm. The DOM effects are different when Angular is in control.
|
||||
|
||||
这时候显示的内容是'Hip! Hooray!',缺乏完美的热情(译注:因为少了一个词嘛)。在Angular的控制下,DOM的效果是不同的。
|
||||
这时候显示的内容是'Hip! Hooray!',缺乏完美的热情(译注:因为少了一个词嘛)。在Angular的控制下,DOM的效果是不同的。
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/structural-directives/template-in-out-of-a2.png' alt="template outside angular")
|
||||
|
@ -387,7 +387,7 @@ block unless-intro
|
|||
* specify the name of the public `input` property for binding
|
||||
(typically the name of the directive itself).
|
||||
|
||||
* 指定`input`属性用于绑定的公开名称(通常就是指令自己的名字)。
|
||||
* 指定`input`属性用于绑定的公开名称(通常就是指令自己的名字)。
|
||||
|
||||
* apply the decorator to our implementation class.
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ include ../_util-fns
|
|||
|
||||
Some code examples display a file that has one or more similarly named companion files. (e.g. hero.component.ts and hero.component.html).
|
||||
|
||||
在一些代码例子中,有的文件拥有一个或多个相似名字的伴随文件。(比如,hero.component.ts和hero.component.html)。
|
||||
在一些代码例子中,有的文件拥有一个或多个相似名字的伴随文件。(比如,hero.component.ts和hero.component.html)。
|
||||
|
||||
The guideline will use the shortcut `hero.component.ts|html|css|spec` to represent those various files. Using this shortcut makes this guide's file structures easier to read and more terse.
|
||||
|
||||
|
@ -135,7 +135,7 @@ a(id='toc')
|
|||
:marked
|
||||
**Do** define one thing (e.g. service or component) per file.
|
||||
|
||||
**坚持**每个文件只定义一样东西(比如服务或者组件)。
|
||||
**坚持**每个文件只定义一样东西(比如服务或者组件)。
|
||||
|
||||
.s-rule.consider
|
||||
:marked
|
||||
|
@ -392,13 +392,13 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Do** use upper camel case for symbols. Match the name of the symbol to the naming of the file.
|
||||
|
||||
**坚持**使用大写驼峰命名法来命名所有符号(类)。保持符号的名字与它所在的文件名字相同。
|
||||
**坚持**使用大写驼峰命名法来命名所有符号(类)。保持符号的名字与它所在的文件名字相同。
|
||||
|
||||
.s-rule.do
|
||||
:marked
|
||||
**Do** append the symbol name with the suffix that it represents.
|
||||
|
||||
**坚持**把符号的类型(比如组件、服务、指令等)附加到符号名的后面。
|
||||
**坚持**把符号的类型(比如组件、服务、指令等)附加到符号名的后面。
|
||||
|
||||
|
||||
.s-why
|
||||
|
@ -500,7 +500,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Do** suffix services with `Service` when it is not clear what they are (e.g. when they are nouns).
|
||||
|
||||
**坚持**当不能从它们的名字里清楚的看出它们是什么的时候(比如它们的名字是名词时),添加`Service`后缀。
|
||||
**坚持**当不能从它们的名字里清楚的看出它们是什么的时候(比如它们的名字是名词时),添加`Service`后缀。
|
||||
|
||||
.s-why
|
||||
:marked
|
||||
|
@ -690,7 +690,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Do** use a custom prefix for the selector of our directives (for instance below we use the prefix `toh` from **T**our **o**f **H**eroes).
|
||||
|
||||
**坚持**为指令的选择器使用自定义的前缀(比如下面例子中,我们使用前缀`toh`,取自**T**our **o**f **H**eroes)。
|
||||
**坚持**为指令的选择器使用自定义的前缀(比如下面例子中,我们使用前缀`toh`,取自**T**our **o**f **H**eroes)。
|
||||
|
||||
.s-why
|
||||
:marked
|
||||
|
@ -1297,7 +1297,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** Nobody wants to search seven levels of folders to find a file. In a folder structure there is no hard and fast number rule, but when a folder has seven to ten files, that may be time to create subfolders. We base it on our comfort level. Use a flatter structure until there is an obvious value (to help the rest of LIFT) in creating a new folder.
|
||||
|
||||
**为何?**没有人愿意搜索7层目录来找一个文件。在目录结构中,没有硬数字约定,但是当目录有七到十个文件时,就是需要新建子目录的时候了。这是基于舒适级别而定的。以平面化结构开始,在有很明显的需求时再新建目录(来配合其他LIFT约定)
|
||||
**为何?**没有人愿意搜索7层目录来找一个文件。在目录结构中,没有硬数字约定,但是当目录有七到十个文件时,就是需要新建子目录的时候了。这是基于舒适级别而定的。以平面化结构开始,在有很明显的需求时再新建目录(来配合其他LIFT约定)
|
||||
|
||||
a(href="#toc") Back to top
|
||||
|
||||
|
@ -1306,7 +1306,7 @@ a(href="#toc") 回到顶部
|
|||
.l-main-section
|
||||
:marked
|
||||
### T-DRY (Try to be DRY)
|
||||
### T-DRY(尝试遵循不重复自己DRY的约定)
|
||||
### T-DRY(尝试遵循不重复自己DRY的约定)
|
||||
<a id="04-05"></a>
|
||||
#### Style 04-05
|
||||
#### 风格04-05
|
||||
|
@ -1315,7 +1315,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Do** be DRY (Don't Repeat Yourself)
|
||||
|
||||
**坚持**不要重复自己(DRY)
|
||||
**坚持**不要重复自己(DRY)
|
||||
|
||||
.s-rule.avoid
|
||||
:marked
|
||||
|
@ -1375,7 +1375,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** Components often have four files (e.g. `*.html`, `*.css`, `*.ts`, and `*.spec.ts`) and can clutter a folder quickly.
|
||||
|
||||
**为何?**组件通常有四个文件(例如`*.html`、 `*.css`、 `*.ts` 和 `*.spec.ts`),它们很容易把一个目录弄乱。
|
||||
**为何?**组件通常有四个文件(例如`*.html`、 `*.css`、 `*.ts` 和 `*.spec.ts`),它们很容易把一个目录弄乱。
|
||||
|
||||
.example-title Overall Folder and File Structure 整体目录和文件结构
|
||||
.filetree
|
||||
|
@ -1413,7 +1413,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
While we prefer our Components to be in their own dedicated folder, another option for small apps is to keep Components flat (not in a dedicated folder). This adds up to four files to the existing folder, but also reduces the folder nesting. Be consistent.
|
||||
|
||||
虽然我们比较喜欢把组件放到它自己独立的目录里面,但是对于很小应用来说,另一个选项是保持平面化结构(不在自己独立的目录里)。这样我们添加最多四个文件到一个已有的目录,但是同时减少的目录的嵌套。保持前后一致就好。
|
||||
虽然我们比较喜欢把组件放到它自己独立的目录里面,但是对于很小应用来说,另一个选项是保持平面化结构(不在自己独立的目录里)。这样我们添加最多四个文件到一个已有的目录,但是同时减少的目录的嵌套。保持前后一致就好。
|
||||
|
||||
a(href="#toc") Back to top
|
||||
|
||||
|
@ -1529,7 +1529,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** When there are a lot of files (e.g. 10+) locating them is easier with a consistent folder structures and more difficult in flat structures.
|
||||
|
||||
**为何?**当有很多文件(10个以上)的时候,在一致的目录结构下面,比在平面化结构下面定位它们要容易得多。
|
||||
**为何?**当有很多文件(10个以上)的时候,在一致的目录结构下面,比在平面化结构下面定位它们要容易得多。
|
||||
|
||||
:marked
|
||||
Below is an example of a small app with folders per component.
|
||||
|
@ -1928,7 +1928,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Do** use `kebab-case` for naming the element selectors of our components.
|
||||
|
||||
**坚持**使用`烤串命名法(中线命名法)`来命名组件的元素选择器。
|
||||
**坚持**使用`烤串命名法(中线命名法)`来命名组件的元素选择器。
|
||||
|
||||
.s-why.s-why-last
|
||||
:marked
|
||||
|
@ -2309,7 +2309,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** Logic will be contained in one place (the Component class) instead of being spread in two places.
|
||||
|
||||
**为何?**所有逻辑都被放置到一个地方(组件类),而不被分离到两个地方。
|
||||
**为何?**所有逻辑都被放置到一个地方(组件类),而不被分离到两个地方。
|
||||
|
||||
.s-why.s-why-last
|
||||
:marked
|
||||
|
@ -2475,7 +2475,7 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** When a service has multiple responsibilities, every Component or Service that injects it now carries the weight of them all.
|
||||
|
||||
**为何?**当服务有多个职责时,每个注入它的组件或者服务都会被迫承担它们的(多个职责)所有的重量。
|
||||
**为何?**当服务有多个职责时,每个注入它的组件或者服务都会被迫承担它们的(多个职责)所有的重量。
|
||||
|
||||
a(href="#toc") Back to top
|
||||
|
||||
|
@ -2599,13 +2599,13 @@ a(href="#toc") 回到顶部
|
|||
:marked
|
||||
**Why?** This makes it easier to test (mock or real) the data calls when testing a component that uses a data service.
|
||||
|
||||
**为何?**在测试使用数据服务的组件时,可以让数据调用更容易被测试(模仿或者真实)。
|
||||
**为何?**在测试使用数据服务的组件时,可以让数据调用更容易被测试(模仿或者真实)。
|
||||
|
||||
.s-why.s-why-last
|
||||
:marked
|
||||
**Why?** Data service implementation may have very specific code to handle the data repository. This may include headers, how to talk to the data, or other services such as `Http`. Separating the logic into a data service encapsulates this logic in a single place hiding the implementation from the outside consumers (perhaps a component), also making it easier to change the implementation.
|
||||
|
||||
**为何?**数据服务的实现可能有非常具体的代码来处理数据仓库,包括数据头(headers)、如何与数据交谈或者其他服务(比如`Http`)。把逻辑分离到数据服务可以把该逻辑封装到一个地方,对外部使用者(比如组件)隐藏具体的实施细节。
|
||||
**为何?**数据服务的实现可能有非常具体的代码来处理数据仓库,包括数据头(headers)、如何与数据交谈或者其他服务(比如`Http`)。把逻辑分离到数据服务可以把该逻辑封装到一个地方,对外部使用者(比如组件)隐藏具体的实施细节。
|
||||
|
||||
a(href="#toc") Back to top
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ code-example(language="html" escape="html").
|
|||
:marked
|
||||
Almost all HTML syntax is valid template syntax. The `<script>` element is a notable exception; it is forbidden, eliminating the risk of script injection attacks. (In practice, `<script>` is simply ignored.)
|
||||
|
||||
几乎所有的HTML语法都是有效的模板语法。但值得注意的例外是`<script>`元素,它被禁用了,以阻止脚本注入攻击的风险。(在实践中,`<script>`只是被忽略了。)
|
||||
几乎所有的HTML语法都是有效的模板语法。但值得注意的例外是`<script>`元素,它被禁用了,以阻止脚本注入攻击的风险。(在实践中,`<script>`只是被忽略了。)
|
||||
|
||||
Some legal HTML doesn’t make much sense in a template. The `<html>`, `<body>`, and `<base>` elements have no useful role in our repertoire. Pretty much everything else is fair game.
|
||||
|
||||
|
@ -224,7 +224,7 @@ block template-expressions-cannot
|
|||
When we see *isUnchanged* in `[disabled]="isUnchanged"`,
|
||||
we know we are referring to that component's `isUnchanged` property.
|
||||
|
||||
当看到包裹在双花括号中的*title*(<code>{{title}}</code>)时,我们就知道`title`是这个数据绑定组件中的一个属性。
|
||||
当看到包裹在双花括号中的*title*(<code>{{title}}</code>)时,我们就知道`title`是这个数据绑定组件中的一个属性。
|
||||
当看到`[disabled]="isUnchanged"`中的*isUnchanged*时,我们就知道我们正在引用该组件的`isUnchanged`属性。
|
||||
|
||||
The component itself is usually the expression *context*, in which case
|
||||
|
@ -320,7 +320,7 @@ block template-expressions-cannot
|
|||
|
||||
在单独的一次消息循环中,被依赖的值不应该改变。
|
||||
如果一个幂等的表达式返回了一个字符串或数字,连续调用它两次,也应该返回相同的字符串或数字。
|
||||
如果表达式返回一个对象(包括`Date`或`Array`),连续调用它两次,也应该返回同一个对象的*引用*。
|
||||
如果表达式返回一个对象(包括`Date`或`Array`),连续调用它两次,也应该返回同一个对象的*引用*。
|
||||
|
||||
.l-main-section#template-statements
|
||||
:marked
|
||||
|
@ -330,7 +330,7 @@ block template-expressions-cannot
|
|||
A template **statement** responds to an **event** raised by a binding target
|
||||
such as an element, component, or directive.
|
||||
|
||||
模板**语句**用来响应由绑定目标(如HTML元素、组件或指令)触发的**事件**对象。
|
||||
模板**语句**用来响应由绑定目标(如HTML元素、组件或指令)触发的**事件**对象。
|
||||
|
||||
We’ll see template statements in the [event binding](#event-binding) section,
|
||||
appearing in quotes to the right of the `=` symbol as in `(event)="statement"`.
|
||||
|
@ -359,7 +359,7 @@ block template-expressions-cannot
|
|||
(with !{__chaining_op}).
|
||||
|
||||
和模板表达式一样,模板*语句*也是一个一个看起来很像JavaScript的语言。
|
||||
模板语句解析器和模板表达式解析器有所不同,它的特别之处在于它既支持基本赋值(`=`)又支持使用分号(`;`)和逗号(`,`)把表达式串起来。
|
||||
模板语句解析器和模板表达式解析器有所不同,它的特别之处在于它既支持基本赋值(`=`)又支持使用分号(`;`)和逗号(`,`)把表达式串起来。
|
||||
|
||||
However, certain #{_JavaScript} syntax is not allowed:
|
||||
|
||||
|
@ -520,7 +520,7 @@ table
|
|||
Binding types other than interpolation have a **target name** to the left of the equal sign,
|
||||
either surrounded by punctuation (`[]`, `()`) or preceded by a prefix (`bind-`, `on-`, `bindon-`).
|
||||
|
||||
除了插值表达式之外的绑定类型,在等号左边都有一个**目标名**,无论是包在括号中(`[]`、`()`)还是用带前缀(`bind-`、`on-`、`bindon-`)的形式。
|
||||
除了插值表达式之外的绑定类型,在等号左边都有一个**目标名**,无论是包在括号中(`[]`、`()`)还是用带前缀(`bind-`、`on-`、`bindon-`)的形式。
|
||||
|
||||
What is that target? Before we can answer that question, we must challenge ourselves to look at template HTML in a new way.
|
||||
|
||||
|
@ -595,7 +595,7 @@ table
|
|||
|
||||
**Attributes are defined by HTML. Properties are defined by the DOM (Document Object Model).**
|
||||
|
||||
**Attribute是由HTML定义的。Property是由DOM(Document Object Model)定义的。**
|
||||
**Attribute是由HTML定义的。Property是由DOM(Document Object Model)定义的。**
|
||||
|
||||
* A few HTML attributes have 1:1 mapping to properties. `id` is one example.
|
||||
|
||||
|
@ -656,7 +656,7 @@ table
|
|||
Setting the button's `disabled` *property* (say, with an Angular binding) disables or enables the button.
|
||||
The value of the *property* matters.
|
||||
|
||||
设置按钮的`disabled` *Property*(比如,通过Angular绑定)可以禁用或启用这个按钮。
|
||||
设置按钮的`disabled` *Property*(比如,通过Angular绑定)可以禁用或启用这个按钮。
|
||||
这就是*Property*的价值。
|
||||
|
||||
**The HTML attribute and the DOM property are not the same thing, even when they have the same name.**
|
||||
|
@ -696,7 +696,7 @@ table
|
|||
The following table summarizes:
|
||||
|
||||
**数据绑定的目标**是DOM中的某些东西。
|
||||
这个目标可能是(元素|组件|指令)的Property、(元素|组件|指令)的事件,或(极少数情况下)一个Attribute名。
|
||||
这个目标可能是(元素|组件|指令)的Property、(元素|组件|指令)的事件,或(极少数情况下)一个Attribute名。
|
||||
下面是的汇总表:
|
||||
|
||||
// If you update this table, UPDATE it in Dart & JS, too.
|
||||
|
@ -797,7 +797,7 @@ table
|
|||
:marked
|
||||
Another example is disabling a button when the component says that it `isUnchanged`:
|
||||
|
||||
另一个例子是当组件说它`isUnchanged`(未改变)时禁用一个按钮:
|
||||
另一个例子是当组件说它`isUnchanged`(未改变)时禁用一个按钮:
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-2')(format=".")
|
||||
:marked
|
||||
Another is setting a property of a directive:
|
||||
|
@ -808,7 +808,7 @@ table
|
|||
Yet another is setting the model property of a custom component (a great way
|
||||
for parent and child components to communicate):
|
||||
|
||||
还有另一个例子是设置一个自定义组件的模型属性(这是父子组件之间通讯的重要途径):
|
||||
还有另一个例子是设置一个自定义组件的模型属性(这是父子组件之间通讯的重要途径):
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-4')(format=".")
|
||||
:marked
|
||||
### One-way *in*
|
||||
|
@ -1087,7 +1087,7 @@ code-example(format="nocode").
|
|||
value, using an expression that resolves to a string.
|
||||
|
||||
Attribute绑定在语法上类似于属性绑定。
|
||||
但方括号中的部分不是一个元素的属性名,而是由一个**`attr`**前缀,紧跟着一个点(`.`),再跟着Attribute的名字组成。
|
||||
但方括号中的部分不是一个元素的属性名,而是由一个**`attr`**前缀,紧跟着一个点(`.`),再跟着Attribute的名字组成。
|
||||
我们可以通过一个能求值为字符串的表达式来设置Attribute的值。
|
||||
|
||||
Here we bind `[attr.colspan]` to a calculated value:
|
||||
|
@ -1107,7 +1107,7 @@ code-example(format="nocode").
|
|||
One of the primary use cases for attribute binding
|
||||
is to set ARIA attributes, as in this example:
|
||||
|
||||
Attribute绑定的主要用例之一是设置ARIA Attribute(译注:ARIA指可访问性,用于给残障人士访问互联网提供便利),就像这个例子中一样:
|
||||
Attribute绑定的主要用例之一是设置ARIA Attribute(译注:ARIA指可访问性,用于给残障人士访问互联网提供便利),就像这个例子中一样:
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'attrib-binding-aria')(format=".")
|
||||
:marked
|
||||
### Class binding
|
||||
|
@ -1122,7 +1122,7 @@ code-example(format="nocode").
|
|||
Instead of an element property between brackets, we start with the prefix `class`,
|
||||
optionally followed by a dot (`.`) and the name of a CSS class: `[class.class-name]`.
|
||||
|
||||
CSS类绑定在语法上类似于属性绑定。但方括号中的部分不是一个元素的属性名,而是包括一个**`class`**前缀,紧跟着一个点(`.`),再跟着CSS类的名字组成。
|
||||
CSS类绑定在语法上类似于属性绑定。但方括号中的部分不是一个元素的属性名,而是包括一个**`class`**前缀,紧跟着一个点(`.`),再跟着CSS类的名字组成。
|
||||
其中后两部分是可选的。形如:`[class.class-name]`。
|
||||
|
||||
The following examples show how to add and remove the application's "special" class
|
||||
|
@ -1133,7 +1133,7 @@ code-example(format="nocode").
|
|||
:marked
|
||||
We can replace that with a binding to a string of the desired class names; this is an all-or-nothing, replacement binding.
|
||||
|
||||
我们可以把它改写为一个绑定到所需CSS类名的绑定;这是一个或者全有或者全无的替换型绑定(译注:即当badCurly有值时class这个Attribute设置的内容会被完全覆盖)。
|
||||
我们可以把它改写为一个绑定到所需CSS类名的绑定;这是一个或者全有或者全无的替换型绑定(译注:即当badCurly有值时class这个Attribute设置的内容会被完全覆盖)。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'class-binding-2')(format=".")
|
||||
|
||||
block dart-class-binding-bug
|
||||
|
@ -1167,7 +1167,7 @@ block dart-class-binding-bug
|
|||
Instead of an element property between brackets, we start with the prefix `style`,
|
||||
followed by a dot (`.`) and the name of a CSS style property: `[style.style-property]`.
|
||||
|
||||
样式绑定在语法上类似于属性绑定。但方括号中的部分不是一个元素的属性名,而是包括一个**`style`**前缀,紧跟着一个点(`.`),再跟着CSS样式的属性名。
|
||||
样式绑定在语法上类似于属性绑定。但方括号中的部分不是一个元素的属性名,而是包括一个**`style`**前缀,紧跟着一个点(`.`),再跟着CSS样式的属性名。
|
||||
形如:`[style.style-property]`。
|
||||
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'style-binding-1')(format=".")
|
||||
|
@ -1275,7 +1275,7 @@ block style-property-name-dart-diff
|
|||
The binding conveys information about the event, including data values, through
|
||||
an **event object named `$event`**.
|
||||
|
||||
这种绑定会通过一个**名叫`$event`的事件对象**传达关于此事件的信息(包括数据值)。
|
||||
这种绑定会通过一个**名叫`$event`的事件对象**传达关于此事件的信息(包括数据值)。
|
||||
|
||||
The shape of the event object is determined by the target event itself.
|
||||
If the target event is a native DOM element event, the `$event` is a
|
||||
|
@ -1303,7 +1303,7 @@ block style-property-name-dart-diff
|
|||
|
||||
If the event belongs to a directive (remember: components are directives), `$event` has whatever shape the directive chose to produce.
|
||||
|
||||
如果这个事件属于指令(记住:组件是指令的一种),那么`$event`便具有指令所生成的形态(译注:比如inputs)。
|
||||
如果这个事件属于指令(记住:组件是指令的一种),那么`$event`便具有指令所生成的形态(译注:比如inputs)。
|
||||
|
||||
<a id="eventemitter"></a>
|
||||
<a id="custom-event"></a>
|
||||
|
@ -1341,7 +1341,7 @@ block style-property-name-dart-diff
|
|||
When the user clicks *delete*, the component invokes the `delete()` method
|
||||
which tells the `EventEmitter` to emit a `Hero` object.
|
||||
|
||||
组件定义了一个`deleteRequest`属性,它是一个`EventEmitter`实例。(译注:`deleteRequest`属性是导出Output属性,是组件与父级组件交互的主要方式之一。参见[输入和输出属性](#input-and-output-properties)和[父组件监听子组件的事件](docs/ts/latest/cookbook/component-communication.html#!#child-to-parent)。我们需要用`@Output()`来装饰它,或者把它添加到组件元数据的`outputs`数组中,它才能在父级组件可见。)
|
||||
组件定义了一个`deleteRequest`属性,它是一个`EventEmitter`实例。(译注:`deleteRequest`属性是导出Output属性,是组件与父级组件交互的主要方式之一。参见[输入和输出属性](#input-and-output-properties)和[父组件监听子组件的事件](docs/ts/latest/cookbook/component-communication.html#!#child-to-parent)。我们需要用`@Output()`来装饰它,或者把它添加到组件元数据的`outputs`数组中,它才能在父级组件可见。)
|
||||
当用户点击*删除*时,组件会调用`delete()`方法,这个方法告诉`EventEmitter`,发出一个`Hero`对象。
|
||||
|
||||
Now imagine a hosting parent component that binds to the `HeroDetailComponent`'s `deleteRequest` event.
|
||||
|
@ -1354,7 +1354,7 @@ block style-property-name-dart-diff
|
|||
When the `deleteRequest` event fires, Angular calls the parent component's `deleteHero` method,
|
||||
passing the *hero-to-delete* (emitted by `HeroDetail`) in the `$event` variable.
|
||||
|
||||
当`deleteRequest`事件触发时,Angular调用父组件的`deleteHero`方法,在`$event`变量中传入*要删除的英雄*(来自`HeroDetail`)。
|
||||
当`deleteRequest`事件触发时,Angular调用父组件的`deleteHero`方法,在`$event`变量中传入*要删除的英雄*(来自`HeroDetail`)。
|
||||
|
||||
### Template statements have side effects
|
||||
### 模板语句有副作用
|
||||
|
@ -1420,7 +1420,7 @@ block style-property-name-dart-diff
|
|||
To remember that the parentheses go inside the brackets, visualize a *banana in a box*.
|
||||
|
||||
要记住“方括号中的圆括号”这种语法,就把它想象成 *盒子里的香蕉* 吧,是不是很形象?
|
||||
(译注:中国读者记起来更简单,方括号又叫中括号,圆括号又叫小括号,显然应该中的在外,小的在内)
|
||||
(译注:中国读者记起来更简单,方括号又叫中括号,圆括号又叫小括号,显然应该中的在外,小的在内)
|
||||
:marked
|
||||
Alternatively, we can use the canonical prefix form:
|
||||
|
||||
|
@ -1628,7 +1628,7 @@ figure.image-display
|
|||
### NgIf
|
||||
We can add an element subtree (an element and its children) to the DOM by binding an `NgIf` directive to a #{_truthy} expression.
|
||||
|
||||
通过把`NgIf`指令绑定到一个真值表达式,我们可以把一个元素的子树(元素及其子元素)添加到DOM上。
|
||||
通过把`NgIf`指令绑定到一个真值表达式,我们可以把一个元素的子树(元素及其子元素)添加到DOM上。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgIf-1')(format=".")
|
||||
|
||||
.alert.is-critical
|
||||
|
@ -1636,7 +1636,7 @@ figure.image-display
|
|||
Don't forget the asterisk (`*`) in front of `ngIf`.
|
||||
For more information, see [\* and <template>](#star-template).
|
||||
|
||||
不要忘记了`ngIf`前面的星号(`*`)。
|
||||
不要忘记了`ngIf`前面的星号(`*`)。
|
||||
要了解更多,参见[\*与<template>](#star-template)。
|
||||
:marked
|
||||
Binding to a #{_falsey} expression removes the element subtree from the DOM.
|
||||
|
@ -1653,7 +1653,7 @@ block dart-no-truthy-falsey
|
|||
We can show and hide an element subtree (the element and its children) with a
|
||||
[class](#class-binding) or [style](#style-binding) binding:
|
||||
|
||||
我们可以通过[类绑定](#class-binding)或[样式绑定](#style-binding)来显示和隐藏一个元素的子树(元素及其子元素)。
|
||||
我们可以通过[类绑定](#class-binding)或[样式绑定](#style-binding)来显示和隐藏一个元素的子树(元素及其子元素)。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'NgIf-3')(format=".")
|
||||
:marked
|
||||
Hiding a subtree is quite different from excluding a subtree with `NgIf`.
|
||||
|
@ -1747,12 +1747,12 @@ block dart-no-truthy-falsey
|
|||
:marked
|
||||
**Do *not*** put the asterisk (`*`) in front of `ngSwitch`. Use the property binding instead.
|
||||
|
||||
**不要**在`ngSwitch`的前面放星号(`*`),而应该用属性绑定。
|
||||
**不要**在`ngSwitch`的前面放星号(`*`),而应该用属性绑定。
|
||||
|
||||
**Do** put the asterisk (`*`) in front of `ngSwitchWhen` and `ngSwitchDefault`.
|
||||
For more information, see [\* and <template>](#star-template).
|
||||
|
||||
**要**把星号(`*`)放在`ngSwitchWhen`和`ngSwitchDefault`的前面。
|
||||
**要**把星号(`*`)放在`ngSwitchWhen`和`ngSwitchDefault`的前面。
|
||||
要了解更多信息,参见[\*与<template>](#star-template)。
|
||||
|
||||
<a id="ngFor"></a>
|
||||
|
@ -1785,7 +1785,7 @@ block dart-no-truthy-falsey
|
|||
Don't forget the asterisk (`*`) in front of `ngFor`.
|
||||
For more information, see [\* and <template>](#star-template).
|
||||
|
||||
不要忘了`ngFor`前面的星号(`*`)。
|
||||
不要忘了`ngFor`前面的星号(`*`)。
|
||||
要了解更多,参见[\*与<template>](#star-template)
|
||||
:marked
|
||||
The text assigned to `*ngFor` is the instruction that guides the repeater process.
|
||||
|
@ -1815,7 +1815,7 @@ block dart-no-truthy-falsey
|
|||
stamping out instances of the element to which it is applied.
|
||||
Angular creates a fresh instance of the template for each hero in the array.
|
||||
|
||||
在前面的两个例子中,`ngFor`指令在`heroes`变量上进行迭代(它是由父组件的`heroes`属性返回的),以其所在的元素为模板“冲压”出很多实例。
|
||||
在前面的两个例子中,`ngFor`指令在`heroes`变量上进行迭代(它是由父组件的`heroes`属性返回的),以其所在的元素为模板“冲压”出很多实例。
|
||||
Angular为数组中的每个英雄创建了此模板的一个全新实例。
|
||||
|
||||
The `let` keyword before `hero` creates a template input variable called `hero`.
|
||||
|
@ -1868,7 +1868,7 @@ block dart-no-truthy-falsey
|
|||
The refreshed list probably contains most, if not all, of the previously displayed heroes.
|
||||
|
||||
例如,我们可以通过重新从服务器查询来刷新英雄列表。
|
||||
刷新后的列表可能包含很多(如果不是全部的话)以前显示过的英雄。
|
||||
刷新后的列表可能包含很多(如果不是全部的话)以前显示过的英雄。
|
||||
|
||||
*We* know this because the `id` of each hero hasn't changed.
|
||||
But Angular sees only a fresh list of new object references.
|
||||
|
@ -1916,7 +1916,7 @@ figure.image-display
|
|||
## `*`与<template>
|
||||
When we reviewed the `NgFor`, `NgIf`, and `NgSwitch` built-in directives, we called out an oddity of the syntax: the asterisk (`*`) that appears before the directive names.
|
||||
|
||||
当我们审视`NgFor`、`NgIf`和`NgSwitch`内建指令时,我们使用了一种古怪的语法:出现在指令名称前面的星号(`*`)。
|
||||
当我们审视`NgFor`、`NgIf`和`NgSwitch`内建指令时,我们使用了一种古怪的语法:出现在指令名称前面的星号(`*`)。
|
||||
|
||||
The `*` is a bit of syntactic sugar that makes it easier to read and write directives that modify HTML layout
|
||||
with the help of templates.
|
||||
|
@ -1951,7 +1951,7 @@ figure.image-display
|
|||
The first expansion step transports the `ngIf` (without the `*` prefix) and its contents
|
||||
into an expression assigned to a `template` directive.
|
||||
|
||||
展开的第一步是把`ngIf`(没有`*`前缀)和它的内容传给一个表达式,再赋值给`template`指令。
|
||||
展开的第一步是把`ngIf`(没有`*`前缀)和它的内容传给一个表达式,再赋值给`template`指令。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'Template-2a')(format=".")
|
||||
:marked
|
||||
The next (and final) step unfolds the HTML into a `<template>` tag and `[ngIf]` [property binding](#property-binding):
|
||||
|
@ -1997,7 +1997,7 @@ block remember-the-brackets
|
|||
Now we can see why the `ngSwitch` itself is not prefixed with an asterisk (*).
|
||||
It does not define content. It's job is to control a collection of templates.
|
||||
|
||||
现在,我们应该明白为什么`ngSwitch`本身不能用星号(*)前缀的原因了吧?
|
||||
现在,我们应该明白为什么`ngSwitch`本身不能用星号(*)前缀的原因了吧?
|
||||
它没有定义内容,它的工作是控制一组模板。
|
||||
|
||||
In this case, it governs two sets of `NgSwitchWhen` and `NgSwitchDefault` directives.
|
||||
|
@ -2005,7 +2005,7 @@ block remember-the-brackets
|
|||
once for the (*) prefixed version and once for the expanded template version.
|
||||
That's exactly what we see in this example:
|
||||
|
||||
上面这种情况下,它管理两组`NgSwitchWhen`和`NgSwitchDefault`指令,一次是(*)前缀的版本,一次是展开模板后的版本。
|
||||
上面这种情况下,它管理两组`NgSwitchWhen`和`NgSwitchDefault`指令,一次是(*)前缀的版本,一次是展开模板后的版本。
|
||||
我们也期待它显示所选模板的值两次。这正是我们在这个例子中看到的:
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/template-syntax/ng-switch-anim.gif' alt="NgSwitch")
|
||||
|
@ -2123,7 +2123,7 @@ figure.image-display
|
|||
This explains how we can disable the submit button by checking `theForm.form.valid`
|
||||
and pass an object with rich information to the parent component's `onSubmit` method.
|
||||
|
||||
这解释了我们该如何通过检查`theForm.form.valid`来禁用提交按钮,以及如何把一个信息量略大的对象传给父组件的`onSubmit`方法(译注:`onSubmit`方法可能会出发一个事件,被父组件监听,参见下面的`输入和输出属性`和[父组件监听子组件的事件](docs/ts/latest/cookbook/component-communication.html#!#child-to-parent)。)
|
||||
这解释了我们该如何通过检查`theForm.form.valid`来禁用提交按钮,以及如何把一个信息量略大的对象传给父组件的`onSubmit`方法(译注:`onSubmit`方法可能会出发一个事件,被父组件监听,参见下面的`输入和输出属性`和[父组件监听子组件的事件](docs/ts/latest/cookbook/component-communication.html#!#child-to-parent)。)
|
||||
|
||||
<a id="inputs-outputs"></a>
|
||||
.l-main-section
|
||||
|
@ -2164,7 +2164,7 @@ figure.image-display
|
|||
The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`.
|
||||
The *source* is either inside quotes (`" "`) or within an interpolation (`{{}}`).
|
||||
|
||||
绑定的*目标*是绑定符:`[]`、`()`或`[()]`中的属性或事件名,*源*则是引号(`" "`)中的部分或插值符号(`{{}}`)中的部分。
|
||||
绑定的*目标*是绑定符:`[]`、`()`或`[()]`中的属性或事件名,*源*则是引号(`" "`)中的部分或插值符号(`{{}}`)中的部分。
|
||||
|
||||
Every member of a **source** directive is automatically available for binding.
|
||||
We don't have to do anything special to access a directive member in a template expression or statement.
|
||||
|
@ -2297,7 +2297,7 @@ h3#aliasing-io 输入/输出属性别名
|
|||
the directive property name on the *left* and the public alias on the *right*:
|
||||
|
||||
我们也能在`inputs`和`outputs`数组中为属性指定别名。
|
||||
我们可以写一个冒号(`:`)分隔的字符串,*左侧*是指令中的属性名,*右侧*则是公开的别名。
|
||||
我们可以写一个冒号(`:`)分隔的字符串,*左侧*是指令中的属性名,*右侧*则是公开的别名。
|
||||
+makeExample('template-syntax/ts/app/my-click.directive.ts', 'my-click-output-2')(format=".")
|
||||
|
||||
<a id="expression-operators"></a>
|
||||
|
@ -2314,7 +2314,7 @@ h3#aliasing-io 输入/输出属性别名
|
|||
:marked
|
||||
<a id="pipe"></a>
|
||||
### The pipe operator ( | )
|
||||
### 管道操作符( | )
|
||||
### 管道操作符( | )
|
||||
The result of an expression might require some transformation before we’re ready to use it in a binding. For example, we might want to display a number as a currency, force text to uppercase, or filter a list and sort it.
|
||||
|
||||
在用到绑定中之前,表达式的结果可能需要一些转换。比如,我们可能希望把一个数字显示成金额、强制文本变成大写,或者过滤一个列表以及排序它。
|
||||
|
@ -2325,7 +2325,7 @@ h3#aliasing-io 输入/输出属性别名
|
|||
|
||||
Angular[管道](./pipes.html)对像这样的小型转换来说是个明智的选择。
|
||||
管道是一个简单的函数,它接受一个输入值,并返回转换结果。
|
||||
它们很容易用于模板表达式中,只要使用**管道操作符(`|`)**就行了。
|
||||
它们很容易用于模板表达式中,只要使用**管道操作符(`|`)**就行了。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'pipes-1')(format=".")
|
||||
:marked
|
||||
The pipe operator passes the result of an expression on the left to a pipe function on the right.
|
||||
|
@ -2361,12 +2361,12 @@ block json-pipe
|
|||
:marked
|
||||
<a id="safe-navigation-operator"></a>
|
||||
### The safe navigation operator ( ?. ) and null property paths
|
||||
### 安全导航操作符( ?. )和空属性路径
|
||||
### 安全导航操作符( ?. )和空属性路径
|
||||
|
||||
The Angular **safe navigation operator (`?.`)** is a fluent and convenient way to guard against null and undefined values in property paths.
|
||||
Here it is, protecting against a view render failure if the `currentHero` is null.
|
||||
|
||||
Angular的**安全导航操作符(`?.`)**是一种流畅而便利的方式,用来保护出现在属性路径中null和undefined值。
|
||||
Angular的**安全导航操作符(`?.`)**是一种流畅而便利的方式,用来保护出现在属性路径中null和undefined值。
|
||||
这意味着,当`currentHero`为空时,保护视图渲染器,让它免于失败。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-2')(format=".")
|
||||
|
||||
|
@ -2392,7 +2392,7 @@ block dart-safe-nav-op
|
|||
Suppose the template expression involves a property path, as in this next example
|
||||
where we’re displaying the `firstName` of a null hero.
|
||||
|
||||
假设模板表达式需要一个属性路径,在下一个例子中,我们要显示一个空(null)英雄的`firstName`。
|
||||
假设模板表达式需要一个属性路径,在下一个例子中,我们要显示一个空(null)英雄的`firstName`。
|
||||
|
||||
code-example(language="html").
|
||||
The null hero's name is {{nullHero.firstName}}
|
||||
|
@ -2451,14 +2451,14 @@ block safe-op-alt
|
|||
Imagine guarding against a null somewhere in a long property path such as `a.b.c.d`.
|
||||
|
||||
这些方法都有价值,但是会显得笨重,特别是当这个属性路径非常长的时候。
|
||||
想象一下在一个很长的属性路径(如`a.b.c.d`)中对空值提供保护。
|
||||
想象一下在一个很长的属性路径(如`a.b.c.d`)中对空值提供保护。
|
||||
|
||||
:marked
|
||||
The Angular safe navigation operator (`?.`) is a more fluent and convenient way to guard against nulls in property paths.
|
||||
The expression bails out when it hits the first null value.
|
||||
The display is blank, but the app keeps rolling without errors.
|
||||
|
||||
Angular安全导航操作符(`?.`)是在属性路径中保护空值的一个更加流畅、便利的方式。
|
||||
Angular安全导航操作符(`?.`)是在属性路径中保护空值的一个更加流畅、便利的方式。
|
||||
表达式会在它遇到第一个空值的时候跳出。
|
||||
显示是空的,但是应用正常工作,而没有发生错误。
|
||||
+makeExample('template-syntax/ts/app/app.component.html', 'safe-6')(format=".")
|
||||
|
|
|
@ -116,7 +116,7 @@ a(id="top")
|
|||
|
||||
1. The Angular Test Environment (forthcoming)
|
||||
|
||||
1. Angular测试环境(即将到来)
|
||||
1. Angular测试环境(即将到来)
|
||||
|
||||
- the Angular test environment and why we need help
|
||||
|
||||
|
@ -140,7 +140,7 @@ a(id="top")
|
|||
|
||||
1. Test a Component (forthcoming)
|
||||
|
||||
1. 测试组件(即将到来)
|
||||
1. 测试组件(即将到来)
|
||||
|
||||
- test the component outside of Angular
|
||||
|
||||
|
@ -152,7 +152,7 @@ a(id="top")
|
|||
|
||||
- simulate interaction with the view (no DOM)
|
||||
|
||||
- 仿真与视图的交互(不涉及DOM)
|
||||
- 仿真与视图的交互(不涉及DOM)
|
||||
|
||||
- use a spy-promise to control asynchronous test flow
|
||||
|
||||
|
@ -160,7 +160,7 @@ a(id="top")
|
|||
|
||||
1. Test a Component in the DOM (forthcoming
|
||||
|
||||
1. 在DOM中测试组件(即将到来)
|
||||
1. 在DOM中测试组件(即将到来)
|
||||
|
||||
- test the component inside the Angular test environment
|
||||
|
||||
|
@ -184,7 +184,7 @@ a(id="top")
|
|||
|
||||
1. Run the tests with karma (forthcoming)
|
||||
|
||||
1. 用Karma运行测试(即将到来)
|
||||
1. 用Karma运行测试(即将到来)
|
||||
|
||||
It’s a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ a(id="tsconfig")
|
|||
the compiler silently defaults the type of a variable to `any` if it cannot infer
|
||||
the type based on how the variable is used. That's what we mean by *implicit `any`*.
|
||||
|
||||
当`noImplicitAny`标志是`false`(默认值)时,
|
||||
当`noImplicitAny`标志是`false`(默认值)时,
|
||||
如果编译器无法根据变量的用途推断出变量的类型,它就会悄悄的把变量类型默认为`any`。
|
||||
这就是*隐式`any`*的含义。
|
||||
|
||||
|
@ -155,7 +155,7 @@ a(id="typings")
|
|||
with npm (it's listed among the *devDependencies* in the `package.json`) and added an npm script
|
||||
to run that tool automatically after *npm* installation completes.
|
||||
|
||||
我们已经用npm安装了这个[typings](https://github.com/typings/typings/blob/master/README.md)工具(它被列在了`package.json`的*devDependencies*中)
|
||||
我们已经用npm安装了这个[typings](https://github.com/typings/typings/blob/master/README.md)工具(它被列在了`package.json`的*devDependencies*中)
|
||||
并添加了一个npm脚本,以便在所有*npm*包安装完之后运行那个工具。
|
||||
|
||||
+makeJson('quickstart/ts/package.1.json', {paths: 'scripts.postinstall'}, 'package.json (postinstall)')(format=".")
|
||||
|
@ -192,7 +192,7 @@ a(id="typings")
|
|||
typical ES2015 features or support testing right out-of-the-box.
|
||||
|
||||
“快速起步”本身不需要这些类型定义,但是文档中的很多例子都需要。
|
||||
如果不能直接编写典型ES2015特性的代码或者写支持外部测试的代码,大部分读者会很失望(所以快速起步中有这些类型定义)。
|
||||
如果不能直接编写典型ES2015特性的代码或者写支持外部测试的代码,大部分读者会很失望(所以快速起步中有这些类型定义)。
|
||||
|
||||
We can also run the *typings* tool ourselves.
|
||||
The following command (re)installs the typings files, as is sometimes necessary when the `postInstall` hook fails to do so.
|
||||
|
|
|
@ -1363,7 +1363,7 @@ code-example(format="").
|
|||
These include things like `let`s and `const`s, arrow functions, default function
|
||||
parameters, and destructuring assignments.
|
||||
|
||||
首先,TypeScript是一个ES2015的超集。任何以前用ES5写的程序(就像PhoneCat范例)都可以开始通过TypeScript
|
||||
首先,TypeScript是一个ES2015的超集。任何以前用ES5写的程序(就像PhoneCat范例)都可以开始通过TypeScript
|
||||
纳入那些添加到ES2015中的新特性。
|
||||
这包括`let`、`const`、箭头函数、函数默认参数以及解构(destructure)赋值。
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ include ../_util-fns
|
|||
|
||||
This time we'll (1) listen to an event and (2) grab the user's input.
|
||||
|
||||
这次,我们将(1)监听一个事件(2)捕获用户输入。
|
||||
这次,我们将(1)监听一个事件(2)捕获用户输入。
|
||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-1-template', 'app/keyup.components.ts (模板 v.1)')(format=".")
|
||||
:marked
|
||||
Angular makes an event object available in the **`$event`** variable,
|
||||
|
@ -139,7 +139,7 @@ figure.image-display
|
|||
|
||||
Angular有一个叫做[**模板引用变量**](./template-syntax.html#ref-vars)的语法特性。
|
||||
这些变量给了我们直接访问元素的能力。
|
||||
通过在标识符前加上井号(#),我们就能定义一个模板引用变量。
|
||||
通过在标识符前加上井号(#),我们就能定义一个模板引用变量。
|
||||
|
||||
Here's an example of using a template reference variable
|
||||
to implement a clever keystroke loopback in an ultra-simple template.
|
||||
|
@ -175,7 +175,7 @@ figure.image-display
|
|||
Angular only updates the bindings (and therefore the screen)
|
||||
if we do something in response to asynchronous events such as keystrokes.
|
||||
|
||||
如果我们在异步事件(如击键)的响应中做点什么,Angular只会更新绑定(并最终影响到屏幕)。
|
||||
如果我们在异步事件(如击键)的响应中做点什么,Angular只会更新绑定(并最终影响到屏幕)。
|
||||
|
||||
That's why we bind the `keyup` event to a statement that does ... well, nothing.
|
||||
We're binding to the number 0, the shortest statement we can think of.
|
||||
|
@ -204,13 +204,13 @@ figure.image-display
|
|||
.l-main-section
|
||||
:marked
|
||||
## Key event filtering (with `key.enter`)
|
||||
## 按键事件过滤(通过`key.enter`)
|
||||
## 按键事件过滤(通过`key.enter`)
|
||||
Perhaps we don't care about every keystroke.
|
||||
Maybe we're only interested in the input box value when the user presses Enter, and we'd like to ignore all other keys.
|
||||
When we bind to the `(keyup)` event, our event handling statement hears *every keystroke*.
|
||||
We could filter the keys first, examining every `$event.keyCode`, and update the `values` property only if the key is Enter.
|
||||
|
||||
或许我们并不关心每一次按键,只在用户按下回车(enter)键的时候,我们才会关心输入框的值,所有其它按键都可以忽略。
|
||||
或许我们并不关心每一次按键,只在用户按下回车(enter)键的时候,我们才会关心输入框的值,所有其它按键都可以忽略。
|
||||
当绑定到`(keyup)`事件的时候,我们的事件处理语句会听到 *每一次按键* 。
|
||||
我们应该先过滤一下按键,比如每一个`$event.keyCode`,并且只有当这个按键是回车键的时候才更新`values`属性。
|
||||
|
||||
|
@ -225,7 +225,7 @@ figure.image-display
|
|||
would be to put the update code in the component.)
|
||||
|
||||
只有在这种情况下,我们才更新组件的`values`属性。
|
||||
(在这个例子中,更新代码是写在事件绑定语句中的。但在实践中更好的方式是把更新代码放到组件中。)
|
||||
(在这个例子中,更新代码是写在事件绑定语句中的。但在实践中更好的方式是把更新代码放到组件中。)
|
||||
+makeExample('user-input/ts/app/keyup.components.ts', 'key-up-component-3' ,'app/keyup.components.ts (v3)')(format=".")
|
||||
:marked
|
||||
Here's how it works.
|
||||
|
@ -237,7 +237,7 @@ figure.image-display
|
|||
.l-main-section
|
||||
:marked
|
||||
## On blur
|
||||
## blur(失去焦点)事件
|
||||
## blur(失去焦点)事件
|
||||
|
||||
Our previous example won't transfer the current state of the input box if the user mouses away and clicks
|
||||
elsewhere on the page. We update the component's `values` property only when the user presses Enter
|
||||
|
@ -337,7 +337,7 @@ figure.image-display
|
|||
input box (our design choice).
|
||||
|
||||
第二条语句的存在理由很充分:在把新的英雄加入列表中之后,我们得清除输入框的值。
|
||||
组件自己做不到这一点,它不能访问输入框(我们的设计选择)。
|
||||
组件自己做不到这一点,它不能访问输入框(我们的设计选择)。
|
||||
|
||||
Although the example *works*, we are rightly wary of JavaScript in HTML.
|
||||
Template statements are powerful. We're supposed to use them responsibly.
|
||||
|
|
|
@ -227,7 +227,7 @@ a(id="plugins")
|
|||
We tap into that pipeline with plugins such as the `uglify` minification plugin:
|
||||
|
||||
Webpack有一条构建流水线,它被划分成多个经过精心定义的阶段(phase)。
|
||||
我们可以把插件(比如`uglify`代码最小化插件)挂到流水线上:
|
||||
我们可以把插件(比如`uglify`代码最小化插件)挂到流水线上:
|
||||
|
||||
+makeExample('webpack/ts-snippets/webpack.config.snippets.ts', 'plugins')(format=".")
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ block install-packages
|
|||
We install the packages listed in `package.json` using `npm`. Enter the
|
||||
following command in a terminal window (command window in Windows):
|
||||
|
||||
我们使用`npm`命令来安装`package.json`中列出的依赖包。请在终端窗口(或Windows的cmd窗口)中输入下列命令:
|
||||
我们使用`npm`命令来安装`package.json`中列出的依赖包。请在终端窗口(或Windows的cmd窗口)中输入下列命令:
|
||||
|
||||
code-example(language="sh").
|
||||
npm install
|
||||
|
@ -235,7 +235,7 @@ block install-packages
|
|||
|
||||
我们通常会在一系列`gyp ERR!`消息后面看到一个`npm WARN`消息。直接忽略即可。
|
||||
有些依赖包可能会尝试用`node-gyp`重新编译它自己。
|
||||
如果重新编译失败了,这个包就会自行恢复(通常是下载一个预编译版本),最终不会影响使用。
|
||||
如果重新编译失败了,这个包就会自行恢复(通常是下载一个预编译版本),最终不会影响使用。
|
||||
|
||||
Just make sure there are no `npm ERR!` messages at the end of `npm install`.
|
||||
|
||||
|
@ -268,7 +268,7 @@ block install-packages
|
|||
Some commands (such as `start`) don't require the `run` keyword.
|
||||
|
||||
我们执行大多数npm脚本的方式都差不多:`npm run`后面跟着*脚本名*。
|
||||
有些命令(比如`start`)不需要`run`关键字。
|
||||
有些命令(比如`start`)不需要`run`关键字。
|
||||
|
||||
Here's what these scripts do:
|
||||
|
||||
|
@ -376,7 +376,7 @@ p.
|
|||
Here we import the Angular 2 core so that our component code can have access to
|
||||
the `@Component` #{_decorator}.
|
||||
|
||||
当我们需要一个模块中的某些东西时,我们引入(import)它。
|
||||
当我们需要一个模块中的某些东西时,我们引入(import)它。
|
||||
在这里,我们导入了Angular 2核心库,以便我们的组件代码能够访问`@Component` #{_decoratorCn}。
|
||||
+makeExcerpt('app/app.component.ts', 'import')
|
||||
|
||||
|
@ -476,7 +476,7 @@ block create-main
|
|||
我们引入了两样东西来启动本应用:
|
||||
|
||||
1. Angular's browser `bootstrap` function
|
||||
1. Angular的浏览器`bootstrap`(引导)函数
|
||||
1. Angular的浏览器`bootstrap`(引导)函数
|
||||
1. The application root component, `AppComponent`.
|
||||
1. 应用的根组件:`AppComponent`。
|
||||
|
||||
|
@ -530,7 +530,7 @@ block create-main
|
|||
但我们应该用正确的方式组织Angular应用的文件结构。
|
||||
启动App与展现视图是两个相互分离的关注点。
|
||||
把这些关注点混在一起会增加不必要的难度。
|
||||
我们可以通过使用不同的引导器(bootstraper)来在不同的环境中启动`AppComponent`。
|
||||
我们可以通过使用不同的引导器(bootstraper)来在不同的环境中启动`AppComponent`。
|
||||
测试组件也变得更容易,因为不需要再运行整个程序才能跑测试。
|
||||
让我们多花一点精力来用*“正确的方式”*实现它。
|
||||
|
||||
|
@ -585,7 +585,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
become more concerned about production qualities such as
|
||||
load times and memory footprint.
|
||||
|
||||
等我们变得更有经验、更关心产品质量(如加载时间、内存足迹等),也可以做出不同的选择。
|
||||
等我们变得更有经验、更关心产品质量(如加载时间、内存足迹等),也可以做出不同的选择。
|
||||
h3#systemjs SystemJS
|
||||
:marked
|
||||
QuickStart uses <a href="https://github.com/systemjs/systemjs" target="_blank">SystemJS</a>
|
||||
|
@ -605,7 +605,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
becomes complicated rather quickly as soon as the file structure diversifies and
|
||||
we start thinking about building for production and performance.
|
||||
|
||||
所有loader(模块加载器)都需要配置,并且文件结构很快就会变得多样,
|
||||
所有loader(模块加载器)都需要配置,并且文件结构很快就会变得多样,
|
||||
loader的配置也会变得复杂,那时候我们就要开始考虑产品构建和性能问题了。
|
||||
|
||||
We suggest becoming well-versed in the loader of your choice.
|
||||
|
@ -654,13 +654,13 @@ h2#index 步骤4:添加#[code index.html]
|
|||
Notice that the module name (after `from`) does not mention a filename extension.
|
||||
In the configuration we tell SystemJS to default the extension to `js`, a JavaScript file.
|
||||
|
||||
注意,模块名(`from`后面)并不包含文件的扩展名。
|
||||
注意,模块名(`from`后面)并不包含文件的扩展名。
|
||||
`package:`配置项告诉SystemJS使用'js'扩展名,也就是加载一个JavaScript文件。
|
||||
|
||||
That makes sense because we transpile TypeScript to JavaScript
|
||||
*before* running the application.
|
||||
|
||||
这是因为我们在运行应用程序*之前*会执行从TypeScript到JavaScript的转译(transpile)。
|
||||
这是因为我们在运行应用程序*之前*会执行从TypeScript到JavaScript的转译(transpile)。
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Transpiling in the browser
|
||||
|
@ -668,7 +668,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
In the live example on plunker we transpile (AKA compile) to JavaScript in the browser
|
||||
on the fly. _That's fine for a demo_.
|
||||
|
||||
在plunker上的在线例子中,我们在浏览器中随时转译(也可以叫编译)到JavaScript。对于演示来说,这足够了。
|
||||
在plunker上的在线例子中,我们在浏览器中随时转译(也可以叫编译)到JavaScript。对于演示来说,这足够了。
|
||||
|
||||
**Do not transpile in the browser during development or for production**.
|
||||
|
||||
|
@ -677,7 +677,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
We strongly recommend transpiling (AKA compiling) to JavaScript during a build phase
|
||||
before running the application for several reasons including:
|
||||
|
||||
我们强烈建议在运行应用之前的build阶段转译(编译)到JavaScript,理由包括:
|
||||
我们强烈建议在运行应用之前的build阶段转译(编译)到JavaScript,理由包括:
|
||||
|
||||
* We see compiler warnings and errors that are hidden from us in the browser.
|
||||
|
||||
|
@ -699,7 +699,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
|
||||
* Precompilation fits into a continuous integration process of build, test, deploy.
|
||||
|
||||
* 预编译更适应CI(持续集成)过程:构建、测试、部署。
|
||||
* 预编译更适应CI(持续集成)过程:构建、测试、部署。
|
||||
|
||||
:marked
|
||||
The `System.import` call tells SystemJS to import the `main` file
|
||||
|
@ -707,7 +707,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
`main` is where we tell Angular to launch the application.
|
||||
We also catch and log launch errors to the console.
|
||||
|
||||
`System.import`调用告诉SystemJS引入`main`文件。(`main.js`,从`main.ts`转译而来的,还记得吧?)
|
||||
`System.import`调用告诉SystemJS引入`main`文件。(`main.js`,从`main.ts`转译而来的,还记得吧?)
|
||||
`main`是我们让Angular启动应用的地方。
|
||||
我们还会把启动过程中的错误捕获并记录到控制台中。
|
||||
|
||||
|
@ -758,7 +758,7 @@ block run-app
|
|||
|
||||
这个命令运行两个并行的node进程
|
||||
1. The TypeScript compiler in watch mode
|
||||
1. TypeScript编译器,运行在监视(watch)模式
|
||||
1. TypeScript编译器,运行在监视(watch)模式
|
||||
1. A static server called **lite-server** that loads `index.html` in a browser
|
||||
and refreshes the browser when application files change
|
||||
1. 一个名叫 **lite-server** 的静态服务器,它把`index.html`加载到浏览器中
|
||||
|
@ -875,7 +875,7 @@ block what-next-ts-overhead
|
|||
We'll probably only touch the `package.json` to update libraries.
|
||||
We'll likely open `index.html` only if we need to add a library or some css stylesheets.
|
||||
|
||||
好消息是:准备阶段(几乎)已经结束了。
|
||||
好消息是:准备阶段(几乎)已经结束了。
|
||||
我们将来可能只是修改`package.json`来升级依赖库。
|
||||
如果需要添加一些库或一些css样式表,我们可以打开`index.html`。
|
||||
:marked
|
||||
|
|
|
@ -285,7 +285,7 @@ figure.image-display
|
|||
|
||||
- Open the browser’s “Developer Tools” (F12 or Ctrl-Shift-I).
|
||||
|
||||
- 打开浏览器的“开发者工具”(F12或者Ctrl-Shift-I)
|
||||
- 打开浏览器的“开发者工具”(F12或者Ctrl-Shift-I)
|
||||
|
||||
- Pick the “sources” section
|
||||
|
||||
|
@ -293,7 +293,7 @@ figure.image-display
|
|||
|
||||
- Open the `1st.spec.ts` test file (Ctrl-P, then start typing the name of the file).
|
||||
|
||||
- 打开测试文件`1st.spec.ts`(Ctrl-P, 然后开始输入文件名)
|
||||
- 打开测试文件`1st.spec.ts`(Ctrl-P, 然后开始输入文件名)
|
||||
|
||||
- Set a breakpoint on the second line of the failing test
|
||||
|
||||
|
@ -305,7 +305,7 @@ figure.image-display
|
|||
|
||||
- Open the console window at the bottom (press Esc)
|
||||
|
||||
- 打开底部的console窗口(按Esc键)
|
||||
- 打开底部的console窗口(按Esc键)
|
||||
|
||||
- Type `null === undefined` and we should see this:
|
||||
|
||||
|
@ -321,19 +321,19 @@ figure.image-display
|
|||
|
||||
- remove the breakpoint (right-click in the “Breakpoints” section and chose “Remove breakpoint”)
|
||||
|
||||
- 移除断点(在“Breakpoints”区域,右键点击“Remove breakpoint”)
|
||||
- 移除断点(在“Breakpoints”区域,右键点击“Remove breakpoint”)
|
||||
|
||||
- Click the “play” icon to resume the test (or F8)
|
||||
|
||||
- 点“play”图标继续运行测试(或F8)
|
||||
- 点“play”图标继续运行测试(或F8)
|
||||
|
||||
And the test finishes. Close the browser tools (click the close box or press F12 or Ctrl-Shift-I)
|
||||
|
||||
这样测试就算完成了。关闭浏览器工具(点击关闭图标或者按F12或Ctrl-Shift-I)
|
||||
这样测试就算完成了。关闭浏览器工具(点击关闭图标或者按F12或Ctrl-Shift-I)
|
||||
|
||||
Fix the test (restore the `.not`); the browser should refresh automatically and all tests pass.
|
||||
|
||||
修复测试(还原`.not`);浏览器会自动刷新,所有测试都通过了。
|
||||
修复测试(还原`.not`);浏览器会自动刷新,所有测试都通过了。
|
||||
|
||||
Congratulations, you’ve completed Jasmine testing 101.
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ code-example(format="" language="html" escape="html").
|
|||
If it had depended on Angular, we’d still be staring at the Jasmine “big-time fail” screen:
|
||||
|
||||
**那是我们幸运!**`Hero`接口并不依赖Angular。
|
||||
如果它依赖于Angular,我们就得面对Jasmine的“大败局”界面了(译注:因为在运行任何测试之前就出现了错误,所以没有任何测试会执行,参见[运行,并失败](#run-and-fail)):
|
||||
如果它依赖于Angular,我们就得面对Jasmine的“大败局”界面了(译注:因为在运行任何测试之前就出现了错误,所以没有任何测试会执行,参见[运行,并失败](#run-and-fail)):
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png'
|
||||
|
|
|
@ -8,7 +8,7 @@ include ../_util-fns
|
|||
Our grand plan is to build an app to help a staffing agency manage its stable of heroes.
|
||||
Even heroes need to find work.
|
||||
|
||||
我们的终极计划是构建一个程序,来帮助职介中心管理英雄围栏(译注:比如WoW登录后看到的那个列表就是“英雄围栏”)。毕竟,英雄们也得养家糊口嘛!
|
||||
我们的终极计划是构建一个程序,来帮助职介中心管理英雄围栏(译注:比如WoW登录后看到的那个列表就是“英雄围栏”)。毕竟,英雄们也得养家糊口嘛!
|
||||
|
||||
Of course we'll only make a little progress in this tutorial. What we do build will
|
||||
have many of the features we expect to find in a full-blown, data-driven application: acquiring and displaying
|
||||
|
@ -58,7 +58,7 @@ p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-6')]。
|
|||
Here's a visual idea of where we're going in this tour, beginning with the "Dashboard"
|
||||
view and our most heroic heroes:
|
||||
|
||||
在本教程中,还引入了一些可视化思想:放一个“仪表盘(Dashboard)”视图,来展示我们最勇敢的英雄。
|
||||
在本教程中,还引入了一些可视化思想:放一个“仪表盘(Dashboard)”视图,来展示我们最勇敢的英雄。
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/toh/heroes-dashboard-1.png' alt="英雄仪表盘的输出")
|
||||
|
@ -83,7 +83,7 @@ figure.image-display
|
|||
Links at the top can take us to either of the main views.
|
||||
We'll click "Heroes". The app takes to the "Heroes" master list view.
|
||||
|
||||
点击“后退(Back)”按钮将把我们带回“仪表盘”。
|
||||
点击“后退(Back)”按钮将把我们带回“仪表盘”。
|
||||
顶部的链接可以把我们带到任何一个主视图。
|
||||
如果我们点击“英雄”链接,本应用将把我们带到“英雄”列表主视图。
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ code-example(language="bash").
|
|||
Everything between the back-ticks at the beginning and end of the template
|
||||
is part of a single template string.
|
||||
|
||||
**小心!**反引号(`)虽然看起来很像单引号('),但它们是截然不同的字符。
|
||||
**小心!**反引号(`)虽然看起来很像单引号('),但它们是截然不同的字符。
|
||||
反引号能做的可不仅仅是标记字符串的边界。
|
||||
在这里,我们只用它来把我们的模板变成多行的,而没有涉及更多用途。
|
||||
所有被反引号引起来的部分,都是一个单一模板字符串的一部分。
|
||||
|
@ -250,7 +250,7 @@ code-example(language="html").
|
|||
|
||||
* Our Tour of Heroes uses the double curly braces of interpolation (a form of one-way data binding)
|
||||
to display the application title and properties of a `Hero` object.
|
||||
* 我们的《英雄指南》使用双大括号(插值表达式 —— 单向数据绑定的一种形式)来显示应用的标题和`Hero`对象的属性。
|
||||
* 我们的《英雄指南》使用双大括号(插值表达式 —— 单向数据绑定的一种形式)来显示应用的标题和`Hero`对象的属性。
|
||||
* We wrote a multi-line template using ES2015’s template strings to make our template readable.
|
||||
* 我们使用ES2105的模板字符串写了一个多行模板,来让我们的模板更有可读性。
|
||||
* We can both display and change the hero’s name after adding a two-way data binding to the `<input>` element
|
||||
|
|
|
@ -80,7 +80,7 @@ code-example(language="bash").
|
|||
first and display mock heroes.
|
||||
|
||||
`HEROES`变量是一个由`Hero`类的实例构成的数组,我们在第一部分定义过它。
|
||||
我们当然希望从一个Web服务中获取这个英雄列表,但别急,我们得把步子迈得小一点儿 —— 先用一组Mock(模拟)出来的英雄。
|
||||
我们当然希望从一个Web服务中获取这个英雄列表,但别急,我们得把步子迈得小一点儿 —— 先用一组Mock(模拟)出来的英雄。
|
||||
|
||||
### Exposing heroes
|
||||
### 导出英雄们
|
||||
|
@ -140,7 +140,7 @@ code-example(language="bash").
|
|||
:marked
|
||||
The leading asterisk (`*`) in front of `ngFor` is a critical part of this syntax.
|
||||
|
||||
`ngFor`的前导星号(`*`)是此语法的重要组成部分。
|
||||
`ngFor`的前导星号(`*`)是此语法的重要组成部分。
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -364,7 +364,7 @@ code-example(language="bash").
|
|||
Remember that the leading asterisk (`*`) in front of `ngIf` is
|
||||
a critical part of this syntax.
|
||||
|
||||
记住,`ngIf`前面的星号(`*`)是语法中的重要组成部分。
|
||||
记住,`ngIf`前面的星号(`*`)是语法中的重要组成部分。
|
||||
:marked
|
||||
When there is no `selectedHero`, the `ngIf` directive removes the hero detail HTML from the DOM.
|
||||
There will be no hero detail elements and no bindings to worry about.
|
||||
|
@ -435,7 +435,7 @@ code-example(language="bash").
|
|||
from the data source (the expression `hero === selectedHero`) to a property of `class`.
|
||||
|
||||
注意,模板中的`class.selected`是括在一对方括号中的。
|
||||
这就是“属性绑定”的语法,一种从数据源(即`hero === selectedHero`表达式)到`class`属性的单向数据流。
|
||||
这就是“属性绑定”的语法,一种从数据源(即`hero === selectedHero`表达式)到`class`属性的单向数据流。
|
||||
+makeExample('toh-2/ts-snippets/app.component.snippets.pt2.ts', 'class-selected-2', 'app.component.ts (Styling each hero)')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
|
|
|
@ -103,7 +103,7 @@ code-example(format="." language="bash").
|
|||
We spell our file names in lower dash case (AKA "kebab-case") so we don't worry about
|
||||
case sensitivity on the server or in source control.
|
||||
|
||||
这里我们使用小写中线命名法(也叫烤串命名法)拼写文件名,所以不用担心它在服务器或者版本控制系统中出现大小写问题。
|
||||
这里我们使用小写中线命名法(也叫烤串命名法)拼写文件名,所以不用担心它在服务器或者版本控制系统中出现大小写问题。
|
||||
<!-- TODO
|
||||
.l-sub-section
|
||||
:marked
|
||||
|
@ -204,7 +204,7 @@ code-example(format=".").
|
|||
:marked
|
||||
Notice that the `hero` property is the ***target*** of a property binding — it's in square brackets to the left of the (=).
|
||||
|
||||
注意,在等号(=)左边方括号中的这个`hero`是属性绑定的***目标***。
|
||||
注意,在等号(=)左边方括号中的这个`hero`是属性绑定的***目标***。
|
||||
|
||||
Angular insists that we declare a ***target*** property to be an ***input*** property.
|
||||
If we don't, Angular rejects the binding and throws an error.
|
||||
|
|
|
@ -24,7 +24,7 @@ include ../_util-fns
|
|||
Because data services are invariably asynchronous,
|
||||
we'll finish the chapter with a promise-based version of the data service.
|
||||
|
||||
因为数据服务通常都是异步的,所以在本章的最后,我们会把它重构为基于承诺(Promise,一种异步编程模式)的版本。
|
||||
因为数据服务通常都是异步的,所以在本章的最后,我们会把它重构为基于承诺(Promise,一种异步编程模式)的版本。
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
|
||||
|
||||
|
@ -111,8 +111,8 @@ code-example(language="bash").
|
|||
If the service name were multi-word, we'd spell the base filename with lower dash case (AKA "kebab-case").
|
||||
The `SpecialSuperHeroService` would be defined in the `special-super-hero.service.ts` file.
|
||||
|
||||
我们遵循的文件命名约定是:服务名称的小写形式(基本名),加上`.service`后缀。
|
||||
如果服务名称包含多个单词,我们就把基本名部分写成中线形式(dash-case,也被称作烤串形式kebab-case)。
|
||||
我们遵循的文件命名约定是:服务名称的小写形式(基本名),加上`.service`后缀。
|
||||
如果服务名称包含多个单词,我们就把基本名部分写成中线形式(dash-case,也被称作烤串形式kebab-case)。
|
||||
比如,`SpecialSuperHeroService`服务应该被定义在`special-super-hero.service.ts`文件中。
|
||||
:marked
|
||||
We name the class `HeroService` and export it for others to import.
|
||||
|
@ -403,7 +403,7 @@ a#child-component
|
|||
我们就快完成了,但还有点事情不太对劲儿。
|
||||
|
||||
## Async Services and Promises
|
||||
## 异步服务与承诺(Promise)
|
||||
## 异步服务与承诺(Promise)
|
||||
Our `HeroService` returns a list of mock heroes immediately.
|
||||
Its `getHeroes` signature is synchronous
|
||||
|
||||
|
@ -429,7 +429,7 @@ a#child-component
|
|||
|
||||
We'll use *promises*.
|
||||
|
||||
我们将使用 *承诺(Promise)* 。
|
||||
我们将使用 *承诺(Promise)* 。
|
||||
|
||||
### The Hero Service makes a promise
|
||||
### `HeroService`会生成一个承诺
|
||||
|
@ -440,7 +440,7 @@ a#child-component
|
|||
|
||||
**承诺** 就是 …… 好吧,它就是一个承诺 —— 在有了结果时,它承诺会回调我们。
|
||||
我们请求一个异步服务去做点什么,然后给它一个回调函数。
|
||||
它会去做(无论用哪种方式),一旦完成,它就会调用我们的回调函数,并通过参数把工作成果或者错误信息传给我们。
|
||||
它会去做(无论用哪种方式),一旦完成,它就会调用我们的回调函数,并通过参数把工作成果或者错误信息传给我们。
|
||||
.l-sub-section
|
||||
:marked
|
||||
We are simplifying. Learn about ES2015 Promises [here](http://exploringjs.com/es6/ch_promises.html) and elsewhere on the web.
|
||||
|
|
|
@ -23,7 +23,7 @@ figure.image-display
|
|||
:marked
|
||||
We'll add Angular’s *Component Router* to our app to satisfy these requirements.
|
||||
|
||||
我们将把Angular*组件路由器*加入应用中,以满足这些需求。(译注:硬件领域中的路由器是用来帮你找到另一台网络设备的,而这里的路由器用于帮你找到一个组件)
|
||||
我们将把Angular*组件路由器*加入应用中,以满足这些需求。(译注:硬件领域中的路由器是用来帮你找到另一台网络设备的,而这里的路由器用于帮你找到一个组件)
|
||||
.l-sub-section
|
||||
:marked
|
||||
The [Routing and Navigation](../guide/router-deprecated.html) chapter covers the router in more detail
|
||||
|
@ -248,7 +248,7 @@ code-example(language="bash").
|
|||
The Angular router is a combination of multiple services (`ROUTER_PROVIDERS`), multiple directives (`ROUTER_DIRECTIVES`),
|
||||
and a configuration decorator (`RouteConfig`). We'll import them all together:
|
||||
|
||||
Angular路由器是由多个服务(`ROUTER_PROVIDERS`)和多个指令(`ROUTER_DIRECTIVES`)以及一个配置装饰器(`RouteConfig`)组成的。我们一次性导入它们。
|
||||
Angular路由器是由多个服务(`ROUTER_PROVIDERS`)和多个指令(`ROUTER_DIRECTIVES`)以及一个配置装饰器(`RouteConfig`)组成的。我们一次性导入它们。
|
||||
+makeExample('toh-5/ts/app/app.component.2.ts', 'import-router', 'app.component.ts (导入router)')(format=".")
|
||||
:marked
|
||||
Next we update the `directives` and `providers` metadata arrays to *include* the router assets.
|
||||
|
@ -310,7 +310,7 @@ code-example(language="bash").
|
|||
要学习更多使用`@RouteConfig`定义路由的知识,请参见[路由](../guide/router-deprecated.html)一章。
|
||||
:marked
|
||||
### Router Outlet
|
||||
### 路由插座(Outlet)
|
||||
### 路由插座(Outlet)
|
||||
|
||||
If we paste the path, `/heroes`, into the browser address bar,
|
||||
the router should match it to the `'Heroes'` route and display the `HeroesComponent`.
|
||||
|
@ -343,7 +343,7 @@ code-example(language="bash").
|
|||
We bind the `RouterLink` directive (another of the `ROUTER_DIRECTIVES`) to an array
|
||||
that tells the router where to navigate when the user clicks the link.
|
||||
|
||||
注意,a标签中的`[routerLink]`绑定。我们把`RouterLink`指令(`ROUTER_DIRECTIVES`中的另一个指令)绑定到一个数组。它将告诉路由器,当用户点击这个链接时,应该导航到哪里。
|
||||
注意,a标签中的`[routerLink]`绑定。我们把`RouterLink`指令(`ROUTER_DIRECTIVES`中的另一个指令)绑定到一个数组。它将告诉路由器,当用户点击这个链接时,应该导航到哪里。
|
||||
|
||||
We define a *routing instruction* with a *link parameters array*.
|
||||
The array only has one element in our little sample, the quoted ***name* of the route** to follow.
|
||||
|
@ -375,7 +375,7 @@ code-example(language="bash").
|
|||
We click the "Heroes" navigation link, the browser bar updates to `/heroes`,
|
||||
and now we see the list of heroes. We are navigating at last!
|
||||
|
||||
我们点击“英雄列表(Heroes)”导航链接,浏览器地址栏更新为`/heroes`,并且看到了英雄列表。我们终于导航过去了!
|
||||
我们点击“英雄列表(Heroes)”导航链接,浏览器地址栏更新为`/heroes`,并且看到了英雄列表。我们终于导航过去了!
|
||||
|
||||
At this stage, our `AppComponent` looks like this.
|
||||
|
||||
|
@ -471,7 +471,7 @@ code-example(language="bash").
|
|||
because Angular doesn't support relative paths _by default_.
|
||||
We _can_ switch to [component-relative paths](../cookbook/component-relative-paths.html) if we prefer.
|
||||
|
||||
我们指定的所有路径_都是相对于该应用的根目录(这里是`app/`)的_。
|
||||
我们指定的所有路径_都是相对于该应用的根目录(这里是`app/`)的_。
|
||||
因为Angular_默认_不支持使用相对于当前模块的路径。
|
||||
只要喜欢,我们也_可以_切换成[相对于组件的路径](../cookbook/component-relative-paths.html)模式。
|
||||
:marked
|
||||
|
@ -542,7 +542,7 @@ code-example(language="bash").
|
|||
The noteworthy differences: we cherry-pick four heroes (2nd, 3rd, 4th, and 5th) with *slice*
|
||||
and stub the `gotoDetail` method until we're ready to implement it.
|
||||
|
||||
不同之处在于:我们使用*slice*函数挑选四个英雄(第2、3、4、5个),并暂时为`gotoDetail`方法提供桩实现 —— 直到我们准备好实现它。
|
||||
不同之处在于:我们使用*slice*函数挑选四个英雄(第2、3、4、5个),并暂时为`gotoDetail`方法提供桩实现 —— 直到我们准备好实现它。
|
||||
|
||||
Refresh the browser and see four heroes in the new dashboard.
|
||||
|
||||
|
@ -619,7 +619,7 @@ code-example(format='').
|
|||
The colon (:) in the path indicates that `:id` is a placeholder to be filled with a specific hero `id`
|
||||
when navigating to the `HeroDetailComponent`.
|
||||
|
||||
路径中的冒号(:)表示`:id`是一个占位符,当导航到这个`HeroDetailComponent`组件时,它将被填入一个特定英雄的`id`。
|
||||
路径中的冒号(:)表示`:id`是一个占位符,当导航到这个`HeroDetailComponent`组件时,它将被填入一个特定英雄的`id`。
|
||||
.l-sub-section
|
||||
:marked
|
||||
Of course we have to import the `HeroDetailComponent` before we create this route:
|
||||
|
@ -774,7 +774,7 @@ code-example(format='').
|
|||
:marked
|
||||
Here's the (nearly) finished `HeroDetailComponent`:
|
||||
|
||||
下面是(几乎)完成的`HeroDetailComponent`:
|
||||
下面是(几乎)完成的`HeroDetailComponent`:
|
||||
+makeExample('toh-5/ts/app/hero-detail.component.ts', 'v2', 'app/hero-detail.component.ts (最新版)')(format=".")
|
||||
:marked
|
||||
|
||||
|
@ -826,7 +826,7 @@ code-example(format='').
|
|||
`import` the `router` reference and inject it in the constructor (along with the `HeroService`):
|
||||
|
||||
`DashboardComponent`还没有路由器。我们使用常规的方式为它加上路由:
|
||||
`import` `router`对象的引用,并且把它注入到构造函数中(就像`HeroService`那样):
|
||||
`import` `router`对象的引用,并且把它注入到构造函数中(就像`HeroService`那样):
|
||||
|
||||
+makeExample('toh-5/ts/app/dashboard.component.ts','import-router', 'app/dashboard.component.ts (节选)')(format=".")
|
||||
+makeExample('toh-5/ts/app/dashboard.component.ts','ctor')(format=".")
|
||||
|
@ -942,7 +942,7 @@ figure.image-display
|
|||
1. Import the `router`
|
||||
1. 导入`router`
|
||||
1. Inject the `router` in the constructor (along with the `HeroService`)
|
||||
1. 把`router`注入到构造函数中(就像`HeroService`那样)
|
||||
1. 把`router`注入到构造函数中(就像`HeroService`那样)
|
||||
1. Implement the `gotoDetail` method by calling the `router.navigate` method
|
||||
with a two-part 'HeroDetail' *link parameters array*.
|
||||
1. 实现`gotoDetail`方法:以`HeroDetail`和*链接参数数组*为参数调用`router.navigate`方法。
|
||||
|
@ -1002,7 +1002,7 @@ figure.image-display
|
|||
We could list multiple style files from different locations if we needed them.
|
||||
As with `templateUrl`, we must specify the path _all the way back to the application root_.
|
||||
|
||||
`styleUrls`属性是一个由样式文件的文件名(包括路径)组成的数组。
|
||||
`styleUrls`属性是一个由样式文件的文件名(包括路径)组成的数组。
|
||||
如果需要,我们还可以列出来自多个不同位置的样式文件。
|
||||
和`templateUrl`一样,我们必须指定_相对于此应用根目录_的路径。
|
||||
:marked
|
||||
|
|
Loading…
Reference in New Issue