Merge remote-tracking branch 'origin/master'

# Conflicts:
#	README.md
#	public/docs/ts/latest/guide/attribute-directives.jade
#	public/docs/ts/latest/guide/component-styles.jade
#	public/docs/ts/latest/guide/dependency-injection.jade
#	public/docs/ts/latest/guide/hierarchical-dependency-injection.jade
#	public/docs/ts/latest/guide/lifecycle-hooks.jade
#	public/docs/ts/latest/guide/pipes.jade
#	public/docs/ts/latest/guide/security.jade
#	public/docs/ts/latest/guide/server-communication.jade
#	public/docs/ts/latest/guide/structural-directives.jade
#	public/docs/ts/latest/quickstart.jade
#	public/docs/ts/latest/testing/testing-an-angular-pipe.jade
#	public/docs/ts/latest/tutorial/index.jade
#	public/docs/ts/latest/tutorial/toh-pt1.jade
#	public/docs/ts/latest/tutorial/toh-pt2.jade
#	public/docs/ts/latest/tutorial/toh-pt3.jade
#	public/docs/ts/latest/tutorial/toh-pt4.jade
#	public/docs/ts/latest/tutorial/toh-pt5.jade
#	public/docs/ts/latest/tutorial/toh-pt6.jade
This commit is contained in:
Zhicheng Wang 2016-07-07 08:15:51 +08:00
commit 0303a18020
40 changed files with 472 additions and 301 deletions

View File

@ -17,13 +17,13 @@ env:
matrix: matrix:
fast_finish: true fast_finish: true
allow_failures: allow_failures:
- env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true" - env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true"
before_install: before_install:
- npm install -g gulp --no-optional - npm install -g gulp --no-optional
before_script: before_script:
- sh -e /etc/init.d/xvfb start - sh -e /etc/init.d/xvfb start
install: install:
- ./script/install.sh - ./scripts/install.sh
- if [[ $PREVIEW == true ]]; then npm install --prefix public/docs/_examples angular/{core,common,compiler,platform-browser,platform-browser-dynamic,http,forms,router-deprecated,router,upgrade}-builds; fi - if [[ $PREVIEW == true ]]; then npm install --prefix public/docs/_examples angular/{core,common,compiler,platform-browser,platform-browser-dynamic,http,forms,router-deprecated,router,upgrade}-builds; fi
script: script:
- gulp $SCRIPT - gulp $SCRIPT

View File

@ -22,6 +22,7 @@ script(src="/resources/js/vendor/angular-material.min.js")
<!-- Angular.io Site JS --> <!-- Angular.io Site JS -->
script(src="/translate/cn/translate.js") script(src="/translate/cn/translate.js")
script(src="/resources/js/site.js") script(src="/resources/js/site.js")
script(src="/resources/js/util.js")
script(src="/resources/js/controllers/app-controller.js") script(src="/resources/js/controllers/app-controller.js")
script(src="/resources/js/controllers/resources-controller.js") script(src="/resources/js/controllers/resources-controller.js")
script(src="/resources/js/directives/cheatsheet.js") script(src="/resources/js/directives/cheatsheet.js")
@ -33,4 +34,7 @@ script(src="/resources/js/directives/copy.js")
script(src="/resources/js/directives/code-tabs.js") script(src="/resources/js/directives/code-tabs.js")
script(src="/resources/js/directives/code-pane.js") script(src="/resources/js/directives/code-pane.js")
script(src="/resources/js/directives/code-example.js") script(src="/resources/js/directives/code-example.js")
script(src="/resources/js/directives/if-docs.js")
script(src="/resources/js/directives/live-example.js")
script(src="/resources/js/directives/ngio-ex-path.js")
script(src="/resources/js/directives/scroll-y-offset-element.js") script(src="/resources/js/directives/scroll-y-offset-element.js")

View File

@ -2,7 +2,7 @@
// #docregion // #docregion
// #docregion first, final // #docregion first, final
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { NgForm } from '@angular/common'; import { NgForm } from '@angular/forms';
import { Hero } from './hero'; import { Hero } from './hero';

View File

@ -20,12 +20,14 @@ include ../../../_includes/_util-fns
- var _indexHtmlDir = 'web'; - var _indexHtmlDir = 'web';
- var _mainDir = 'web'; - var _mainDir = 'web';
//- Deprecated
mixin liveExampleLink(linkText, exampleUrlPartName) mixin liveExampleLink(linkText, exampleUrlPartName)
- var text = linkText || '在线例子'; - var text = linkText || '在线例子';
- var ex = exampleUrlPartName || getExampleName(); - var ex = exampleUrlPartName || getExampleName();
- var href = 'http://angular-examples.github.io/' + ex; - var href = 'http://angular-examples.github.io/' + ex;
a(href='#{href}' target="_blank")= text a(href='#{href}' target="_blank")= text
//- Deprecated
mixin liveExampleLink2(linkText, exampleUrlPartName) mixin liveExampleLink2(linkText, exampleUrlPartName)
- var srcText = attributes.srcText || '查看源码'; - var srcText = attributes.srcText || '查看源码';
- var ex = exampleUrlPartName || attributes.example || getExampleName(); - var ex = exampleUrlPartName || attributes.example || getExampleName();

View File

@ -10,21 +10,12 @@ block ctor-syntax
We also leveraged Dart's constructor syntax for declaring parameters and We also leveraged Dart's constructor syntax for declaring parameters and
initializing properties simultaneously. initializing properties simultaneously.
block service-in-its-own-file
//- N/A
block one-class-per-file-ts-tradeoffs
//- N/A
block injectable-not-always-needed-in-ts block injectable-not-always-needed-in-ts
//- The [Angular 2 Dart Transformer](https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer) //- The [Angular 2 Dart Transformer](https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer)
//- generates static code to replace the use of dart:mirrors. It requires that types be //- generates static code to replace the use of dart:mirrors. It requires that types be
//- identified as targets for static code generation. Generally this is achieved //- identified as targets for static code generation. Generally this is achieved
//- by marking the class as @Injectable (though there are other mechanisms). //- by marking the class as @Injectable (though there are other mechanisms).
block ts-any-decorator-will-do
//- N/A
block always-include-paren block always-include-paren
:marked :marked
Always write `@Injectable()`, not just `@Injectable`. Always write `@Injectable()`, not just `@Injectable`.
@ -43,11 +34,6 @@ block real-logger
A real implementation would probably use the A real implementation would probably use the
[logging package](https://pub.dartlang.org/packages/logging). [logging package](https://pub.dartlang.org/packages/logging).
block canonical-provider-expr
| &nbsp;that creates a new instance of the&nbsp;
a(href="../api/core/Provider-class.html") Provider
| &nbsp;class:
block provider-ctor-args block provider-ctor-args
- var _secondParam = 'named parameter, such as <code>useClass</code>' - var _secondParam = 'named parameter, such as <code>useClass</code>'
:marked :marked

View File

@ -8,16 +8,9 @@ block includes
- var _Angular_http_library = 'Dart <a href="' + _httpUrl + '"><b>http</b></a> library' - var _Angular_http_library = 'Dart <a href="' + _httpUrl + '"><b>http</b></a> library'
block demos-list block demos-list
li #[a(href="#http-client") HTTP client: Tour of Heroes] :marked
li #[a(href="#cors") JSONP client: Wikipedia to fetch data from a service that does not support CORS] #[b (under development)] - [HTTP client: Tour of Heroes](#http-client)
- [JSONP client: Wikipedia to fetch data from a service that does not support CORS (**under development**)](#cors)
block rxjs-import
//- N/A
block http-client
block system-config-of-http
//- N/A
block http-providers block http-providers
:marked :marked
@ -50,9 +43,6 @@ block getheroes-and-addhero
programming in Dart, or the tutorial on programming in Dart, or the tutorial on
[_Asynchronous Programming: Futures_](https://www.dartlang.org/docs/tutorials/futures/). [_Asynchronous Programming: Futures_](https://www.dartlang.org/docs/tutorials/futures/).
block rxjs
//- N/A
block parse-json block parse-json
:marked :marked
The response data are in JSON string form. The response data are in JSON string form.
@ -65,7 +55,7 @@ block error-handling
block hlc-error-handling block hlc-error-handling
:marked :marked
Back in the `HeroListComponent`, we wrapped our call to Back in the `HeroListComponent`, we wrapped our call to
`#{_priv}heroService.getHeroes()` in a `try` clause. When an exception is `!{_priv}heroService.getHeroes()` in a `try` clause. When an exception is
caught, the `errorMessage` variable &mdash; which we've bound conditionally in the caught, the `errorMessage` variable &mdash; which we've bound conditionally in the
template &mdash; gets assigned to. template &mdash; gets assigned to.
@ -75,9 +65,6 @@ block hero-list-comp-add-hero
awaits for the *service's* asynchronous `addHero()` to return, and when it does, awaits for the *service's* asynchronous `addHero()` to return, and when it does,
the new hero is added to the `heroes` list for presentation to the user. the new hero is added to the `heroes` list for presentation to the user.
block promises
//- N/A
block wikipedia-jsonp+ block wikipedia-jsonp+
:marked :marked
Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API. Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API.

View File

@ -1,8 +1,5 @@
include ../_util-fns include ../_util-fns
+includeShared('{ts}', 'intro') +includeShared('{ts}', 'intro')
p Run the #[+liveExampleLink2('', 'toh-5')].
+includeShared('{ts}', 'main') +includeShared('{ts}', 'main')

View File

@ -33,7 +33,8 @@ include ../_util-fns
.callout.is-helpful .callout.is-helpful
header Source code header Source code
p Run the #[+liveExampleLink2('', 'toh-1')] for this part. :marked
Run the <live-example></live-example> for this part.
:marked :marked
## Keep the app compiling and running ## Keep the app compiling and running

View File

@ -6,8 +6,8 @@ include ../_util-fns
Well expand our Tour of Heroes app to display a list of heroes, Well expand our Tour of Heroes app to display a list of heroes,
allow the user to select a hero, and display the heros details. allow the user to select a hero, and display the heros details.
p Run the #[+liveExampleLink2('', 'toh-2')] for this part. Run the <live-example></live-example> for this part.
:marked
Lets take stock of what well need to display a list of heroes. Lets take stock of what well need to display a list of heroes.
First, we need a list of heroes. We want to display those heroes in the views template, First, we need a list of heroes. We want to display those heroes in the views template,
so well need a way to do that. so well need a way to do that.
@ -294,8 +294,8 @@ code-example(language="bash").
* We added the ability to select a hero and show the heros details * We added the ability to select a hero and show the heros details
* We learned how to use the built-in directives `ngIf` and `ngFor` in a components template * We learned how to use the built-in directives `ngIf` and `ngFor` in a components template
p Run the #[+liveExampleLink2('', 'toh-2')] for this part. Run the <live-example></live-example> for this part.
:marked
### The Road Ahead ### The Road Ahead
Our Tour of Heroes has grown, but its far from complete. Our Tour of Heroes has grown, but its far from complete.
We can't put the entire app into a single component. We can't put the entire app into a single component.

View File

@ -4,7 +4,7 @@ include ../_util-fns
Our app is growing. Our app is growing.
Use cases are flowing in for reusing components, passing data to components, and creating more reusable assets. Let's separate the heroes list from the hero details and make the details component reusable. Use cases are flowing in for reusing components, passing data to components, and creating more reusable assets. Let's separate the heroes list from the hero details and make the details component reusable.
p Run the #[+liveExampleLink2('', 'toh-3')] for this part. Run the <live-example></live-example> for this part.
.l-main-section .l-main-section
:marked :marked
@ -240,7 +240,7 @@ code-example(format=".")
* We learned to bind a parent component to a child component. * We learned to bind a parent component to a child component.
* We learned to declare the application directives we need in a `directives` list. * We learned to declare the application directives we need in a `directives` list.
p Run the #[+liveExampleLink2('', 'toh-3')] for this part. Run the <live-example></live-example> for this part.
.l-main-section .l-main-section
:marked :marked

View File

@ -15,7 +15,7 @@ include ../_util-fns
Because data services are invariably asynchronous, Because data services are invariably asynchronous,
we'll finish the chapter with a **!{_Promise}**-based version of the data service. we'll finish the chapter with a **!{_Promise}**-based version of the data service.
p Run the #[+liveExampleLink2('', 'toh-4')] for this part. Run the <live-example></live-example> for this part.
.l-main-section .l-main-section
:marked :marked

View File

@ -18,7 +18,7 @@ figure.image-display
The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail
than we will in this tutorial. than we will in this tutorial.
p Run the #[+liveExampleLink2('', 'toh-5')] for this part. Run the <live-example></live-example> for this part.
.l-main-section .l-main-section
:marked :marked
@ -653,11 +653,10 @@ figure.image-display
.l-main-section .l-main-section
:marked :marked
## Application structure and code ## Application structure and code
p.
Review the sample source code in the #[+liveExampleLink2('', 'toh-5')] for this chapter. Review the sample source code in the <live-example></live-example> for this chapter.
Verify that we have the following structure: Verify that we have the following structure:
:marked
.filetree .filetree
.file angular2_tour_of_heroes .file angular2_tour_of_heroes
.children .children

View File

@ -4,12 +4,14 @@ include ../../../_includes/_util-fns
- var _docsFor = 'ts'; - var _docsFor = 'ts';
//- Other values match the defaults. //- Other values match the defaults.
//- Deprecated
mixin liveExampleLink(linkText, exampleUrlPartName) mixin liveExampleLink(linkText, exampleUrlPartName)
- var text = linkText || 'live example'; - var text = linkText || 'live example';
- var ex = exampleUrlPartName || getExampleName(); - var ex = exampleUrlPartName || getExampleName();
- var href = '/resources/live-examples/' + ex + '/ts/plnkr.html'; - var href = '/resources/live-examples/' + ex + '/ts/plnkr.html';
a(href='#{href}' target="_blank")= text a(href='#{href}' target="_blank")= text
//- Deprecated
mixin liveExampleLink2(linkText, exampleUrlPartName) mixin liveExampleLink2(linkText, exampleUrlPartName)
//- In Dart this gives 2 links: to the demo and to the source. //- In Dart this gives 2 links: to the demo and to the source.
+liveExampleLink(linkText, exampleUrlPartName) +liveExampleLink(linkText, exampleUrlPartName)

View File

@ -33,7 +33,7 @@ h2#devenv Step 1. Set up the Development Environment
if they are not already on your machine. if they are not already on your machine.
.l-sub-section .l-sub-section
:marked :marked
**Verify that you are running node `v5.x.x` and npm `3.x.x`** **Verify that you are running node `v4.x.x` and npm `3.x.x`**
by running `node -v` and `npm -v` in a terminal/console window. by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors. Older versions produce errors.
:marked :marked

View File

@ -19,10 +19,9 @@ block includes
* [pass values into the directive using data binding](#bindings) * [pass values into the directive using data binding](#bindings)
* [使用数据绑定把值传到指令中](#bindings) * [使用数据绑定把值传到指令中](#bindings)
p Try the #[+liveExampleLink2()]. Try the <live-example></live-example>.
p 试用#[+liveExampleLink2("在线例子")] 试试<live-example></live-example>
:marked
## Directives overview ## Directives overview
## 指令概览 ## 指令概览

View File

@ -33,8 +33,9 @@ block includes
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls) * [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
* [附录2使用相对URL加载样式](#relative-urls) * [附录2使用相对URL加载样式](#relative-urls)
p Run the #[+liveExampleLink2()] of the code shown in this chapter. Run the <live-example></live-example> of the code shown in this chapter.
p 运行本章这些代码的#[+liveExampleLink2("在线例子")]
运行本章这些代码的<live-example></live-example>。
.l-main-section .l-main-section
:marked :marked

View File

@ -29,8 +29,9 @@ block includes
- [Summary](#summary) - [Summary](#summary)
- [总结](#summary) - [总结](#summary)
p Run the #[+liveExampleLink2()]. Run the <live-example></live-example>.
p 运行#[+liveExampleLink2('在线例子')].
运行<live-example></live-example>.
.l-main-section#why-di .l-main-section#why-di
:marked :marked
@ -658,10 +659,6 @@ block injectable-not-always-needed-in-ts
fact `InjectableMetadata` #{_decorator}s that fact `InjectableMetadata` #{_decorator}s that
identify a class as a target for instantiation by an injector. identify a class as a target for instantiation by an injector.
如果真的想要这样做,我们*可以*添加它。但是这不是必须的,因为`HerosComponent`已经被`@Component`标识,这个装饰器类(像`@Directive`和`@Pipe`一样,我们一会儿将会学到)
是一个<a href="#{injMetaUrl}">InjectableMetadata</a>的子类型。实际上,`InjectableMetadata`装饰器标识着一个类是注入器实例化的目标。
block ts-any-decorator-will-do block ts-any-decorator-will-do
.l-sub-section .l-sub-section
:marked :marked
@ -798,10 +795,10 @@ code-example(format="nocode").
//- Dart limitation: the provide function isn't const so it cannot be used in an annotation. //- Dart limitation: the provide function isn't const so it cannot be used in an annotation.
- var __andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> object literal'; - var __andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> object literal';
- var __andProvideFn = _docsFor == 'dart' ? '' : '和 <i>provide</i> 对象';
#provide #provide
:marked :marked
### *Provider* 类!{__andProvideFn} ### The *Provider* class !{__andProvideFn}
:marked :marked
We wrote the `providers` #{_array} like this: We wrote the `providers` #{_array} like this:
@ -813,8 +810,6 @@ p
| This is actually a short-hand expression for a provider registration | This is actually a short-hand expression for a provider registration
block canonical-provider-expr block canonical-provider-expr
| &nbsp;using a <i>provider</i> object literal with two properties: | &nbsp;using a <i>provider</i> object literal with two properties:
p
| 这实际上是用_provider_对象的字面量注册供应商的缩写表达式。
+makeExample('dependency-injection/ts/app/providers.component.ts','providers-3') +makeExample('dependency-injection/ts/app/providers.component.ts','providers-3')
@ -1322,9 +1317,6 @@ block dart-map-alternative
Framework developers may take this approach when they Framework developers may take this approach when they
must acquire services generically and dynamically. must acquire services generically and dynamically.
框架的开发人员可能会需要此方法 —— 当他们不得不以通用和动态的方式获取服务时。
// #enddocregion appendix-explicit-injector-2
block one-class-per-file-ts-tradeoffs block one-class-per-file-ts-tradeoffs
.l-main-section#one-class-per-file .l-main-section#one-class-per-file
:marked :marked

View File

@ -21,8 +21,9 @@ block includes
在本章中,我们将浏览这些要点,并写点代码来验证它。 在本章中,我们将浏览这些要点,并写点代码来验证它。
p Try the #[+liveExampleLink2()]. Try the <live-example></live-example>.
p 试试#[+liveExampleLink2("在线例子")].
试试<live-example></live-example>.
.l-main-section .l-main-section
:marked :marked

View File

@ -62,7 +62,7 @@ block includes
* [AfterContentInit和AfterContentChecked](#aftercontent) * [AfterContentInit和AfterContentChecked](#aftercontent)
p Try the #[+liveExampleLink2()]. Try the <live-example></live-example>.
p 试一试#[+liveExampleLink2('在线例子')]。 p 试一试#[+liveExampleLink2('在线例子')]。
@ -327,18 +327,19 @@ a(id="other-lifecycles")
第三方库也可能会实现它们自己的钩子,以便让我们这些开发者在使用时能做更多的控制。 第三方库也可能会实现它们自己的钩子,以便让我们这些开发者在使用时能做更多的控制。
a#the-sample .l-main-section#the-sample
.l-main-section :marked
h2 Lifecycle exercises ## Lifecycle exercises
h2 生命周期练习
p. ## 生命周期练习
The #[+liveExampleLink()]
The <live-example></live-example>
demonstrates the lifecycle hooks in action through a series of exercises demonstrates the lifecycle hooks in action through a series of exercises
presented as components under the control of the root `AppComponent`. presented as components under the control of the root `AppComponent`.
p #[+liveExampleLink('运行在线范例')]通过在受控于根组件`AppComponent`的一些组件上进行的一系列练习,演示了生命周期钩子的运作方式。 <live-example></live-example>通过在受控于根组件`AppComponent`的一些组件上进行的一系列练习,演示了生命周期钩子的运作方式。
:marked
They follow a common pattern: a *parent* component serves as a test rig for They follow a common pattern: a *parent* component serves as a test rig for
a *child* component that illustrates one or more of the lifecycle hook methods. a *child* component that illustrates one or more of the lifecycle hook methods.

View File

@ -17,7 +17,7 @@ include ../_util-fns
如果你的电脑上还没有装过,请<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">立即获取它</a> 如果你的电脑上还没有装过,请<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">立即获取它</a>
**Verify that you are running at least node `v5.x.x` and npm `3.x.x`** **Verify that you are running at least node `v4.x.x` and npm `3.x.x`**
by running `node -v` and `npm -v` in a terminal/console window. by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors. Older versions produce errors.

View File

@ -23,16 +23,11 @@ block includes
We almost think of them as styles. We almost think of them as styles.
In fact, we'd like to apply them in our HTML templates as we do styles. In fact, we'd like to apply them in our HTML templates as we do styles.
显然,对某些值做一点修饰会显得更友好。我们很快就会发现,相同的“数据转换”工作要重复做很多次,甚至会出现在很多应用中。
我们甚至可以把它看做样式。
事实上我们确实更喜欢像样式那样把它们应用到HTML模板中。
p.
Introducing Angular pipes, a way to write display-value transformations that we can declare in our HTML! Introducing Angular pipes, a way to write display-value transformations that we can declare in our HTML!
Try the #[+liveExampleLink2()]. Try the <live-example></live-example>.
p.
欢迎来到Angular“管道(Pipe)”的世界!我们可以把这种简单的“值-显示”转换器声明在HTML中。 欢迎来到Angular“管道(Pipe)”的世界!我们可以把这种简单的“值-显示”转换器声明在HTML中。
试试#[+liveExampleLink2('在线例子')]. 试试<live-example></live-example>。
.l-main-section .l-main-section
:marked :marked
@ -258,18 +253,14 @@ figure.image-display
Angular built-in pipes are pre-registered. Angular built-in pipes are pre-registered.
Custom pipes must be registered manually. Custom pipes must be registered manually.
如果我们忘了列出自定义管道Angular会报告一个错误。
我们不用在以前的例子中列出`DatePipe`是因为所有的Angular内建管道都被预先注册过了。
而自定义管道就必须被手动注册。
p. p.
If we try the #[+liveExampleLink()], If we try the #[+liveExampleLink()],
we can probe its behavior by changing the value and the optional exponent in the template. we can probe its behavior by changing the value and the optional exponent in the template.
p.
试试这个#[+liveExampleLink('在线例子')],然后在模板中修改能量值和可选的放大指数,就能探测它行为方式。
:marked :marked
If we try the <live-example></live-example>,
we can probe its behavior by changing the value and the optional exponent in the template.
## Power Boost Calculator (extra-credit) ## Power Boost Calculator (extra-credit)
## 能力倍增计算器(加分项) ## 能力倍增计算器(加分项)
@ -346,12 +337,10 @@ a#change-detection
p. p.
When we run the sample now we see odd behavior (try it in the #[+liveExampleLink()]). When we run the sample now we see odd behavior (try it in the #[+liveExampleLink()]).
Every hero we add is a flying hero but none of them are displayed. Every hero we add is a flying hero but none of them are displayed.
p.
如果我们现在就运行这个例子,我们会看到一些古怪的行为(在#[+liveExampleLink('在线例子')]中试试)。
我们添加的每个英雄都会飞,但他们一个都没有显示出来。
:marked :marked
When we run the sample now we see odd behavior (try it in the <live-example></live-example>).
Every hero we add is a flying hero but none of them are displayed.
Although we're not getting the behavior we want, Angular isn't broken. Although we're not getting the behavior we want, Angular isn't broken.
It's just using a different change detection algorithm &mdash; one that ignores changes to the list or any of its items. It's just using a different change detection algorithm &mdash; one that ignores changes to the list or any of its items.
@ -527,11 +516,10 @@ block pure-change
我们可以从`FlyingHeroesComponent`派生出一个`FlyingHeroesImpureComponent`。 我们可以从`FlyingHeroesComponent`派生出一个`FlyingHeroesImpureComponent`。
+makeExample('pipes/ts/app/flying-heroes.component.ts','impure-component','app/flying-heroes.component.ts (FlyingHeroesImpureComponent)')(format='.') +makeExample('pipes/ts/app/flying-heroes.component.ts','impure-component','app/flying-heroes.component.ts (FlyingHeroesImpureComponent)')(format='.')
p. :marked
The only substantive change is the pipe. The only substantive change is the pipe.
We can confirm in the #[+liveExampleLink()] that the #[i flying heroes] We can confirm in the <live-example></live-example> that the _flying heroes_
display updates as we enter new heroes even when we mutate the display updates as we enter new heroes even when we mutate the `heroes` #{_array}.
#[code heroes] #{_array}.
p. p.
唯一的重大改动就是管道。 唯一的重大改动就是管道。

View File

@ -1458,7 +1458,7 @@ h4#snapshot <i>快照</i>不需要可观察no-observable时的替代方
假如我们很确定`HeroDetailComponent`组件*永远、永远*不会被复用,每次导航到英雄详情时都会重新创建该组件。 假如我们很确定`HeroDetailComponent`组件*永远、永远*不会被复用,每次导航到英雄详情时都会重新创建该组件。
The router offers a *Snapshot* alternative that gives us the initial value of the route parameters. The router offers a *Snapshot* alternative that gives us the initial value of the route parameters.
We don't need to subscribe. We don't have to unsubscribe in `ngDestroy`. We don't need to subscribe. We don't have to unsubscribe in `ngOnDestroy`.
It's much simpler to write and read: It's much simpler to write and read:
路由器提供了一个备选方案:*快照snapshot*,它会给我们路由参数的初始值。这样我们就不用订阅,也就不用不得不在`ngDestroy`中反订阅了。 路由器提供了一个备选方案:*快照snapshot*,它会给我们路由参数的初始值。这样我们就不用订阅,也就不用不得不在`ngDestroy`中反订阅了。

View File

@ -40,11 +40,9 @@ block includes
* [Auditing Angular Applications](#code-review) * [Auditing Angular Applications](#code-review)
* [审计Angular应用程序](#code-review) Try the <live-example></live-example> of the code shown in this chapter.
p Try the #[+liveExampleLink2()] of the code shown in this chapter. 运行<live-example></live-example>来试用本章中的代码。
p 运行#[+liveExampleLink2('在线例子')]
.l-main-section .l-main-section
h2#report-issues Reporting Vulnerabilities h2#report-issues Reporting Vulnerabilities

View File

@ -32,90 +32,96 @@ block includes
!{_Angular_http_libraryCn}简化了**XHR**和**JSONP** API的编程这就是本章所要讲的。 !{_Angular_http_libraryCn}简化了**XHR**和**JSONP** API的编程这就是本章所要讲的。
ul - [HTTP client sample overview](#http-client)
li #[a(href="#http-client") HTTP client sample overview]
li #[a(href="#http-client") HTTP客户端范例概览]
li #[a(href="#fetch-data") Fetch data with http.get]
li #[a(href="#fetch-data") 通过http.get获取数据]
+ifDocsFor('ts')
li #[a(href="#rxjs") RxJS Observable of HTTP Responses]
li #[a(href="#rxjs") HTTP响应中的RxJS 可观察对象(Observable)]
li #[a(href="#enable-rxjs-operators") Enabling RxJS Operators]
li #[a(href="#enable-rxjs-operators") 启用RxJS操作(Operator)函数]
li #[a(href="#extract-data") Extract JSON data]
li #[a(href="#extract-data") 提取JSON数据]
li #[a(href="#error-handling") Error handling]
li #[a(href="#error-handling") 错误处理]
li #[a(href="#update") Send data to the server]
li #[a(href="#update") 把数据发送到服务器]
+ifDocsFor('ts') - [HTTP客户端范例概览](#http-client)
li #[a(href="#promises") Promises instead of observables]
- [Fetch data with http.get](#fetch-data)
- [用http.get获取数据](#fetch-data)
<li if-docs="ts"> [RxJS Observable of HTTP Responses](#rxjs)</li>
<li if-docs="ts"> [HTTP响应中的RxJS可观察对象](#rxjs)</li>
<li if-docs="ts"> [Enabling RxJS Operators](#enable-rxjs-operators)</li>
<li if-docs="ts"> [启用RxJS操作符](#enable-rxjs-operators)</li>
- [Extract JSON data](#extract-data)
- [提取JSON数据](#extract-data)
- [Error handling](#error-handling)
- [错误处理](#error-handling)
- [Send data to the server](#update)
- [把数据发送到服务器](#update)
<li if-docs="ts"> [Promises instead of observables](#promises)</li>
<li if-docs="ts"> [使用承诺(Promise)来取代可观察对象(Observable)](#promises)</li>
- [Cross-origin requests: Wikipedia example](#cors)
- [跨域请求Wikipedia例子](#cors)
<ul if-docs="ts">
<li> [Set query string parameters](#search-parameters)</li>
<li> [设置查询参数](#search-parameters)</li>
<li> [Debounce search term input](#more-observables)</li>
<li> [限制搜索词输入频率](#more-observables)</li>
</ul>
- [Appendix: the in-memory web api service](#in-mem-web-api)
- [附录内存中的Web API服务](#in-mem-web-api)
li #[a(href="#promises") 使用承诺(Promise)来取代可观察对象(Observable)] We illustrate these topics with code that you can <live-example>run live</live-example>.
li #[a(href="#cors") Cross-origin requests: Wikipedia example] 我们在<live-example>在线例子</live-example>中展示了这些主题,你可以在浏览器中运行它们。
li #[a(href="#cors") 跨域请求Wikipedia例子]
+ifDocsFor('ts')
ul
li #[a(href="#search-parameters") Set query string parameters]
li #[a(href="#search-parameters") 设置查询参数]
li #[a(href="#more-observables") Debounce search term input]
li #[a(href="#more-observables") 限制搜索框条目输入频率]
li #[a(href="#in-mem-web-api") Appendix: the in-memory web api service]
li #[a(href="#in-mem-web-api") 附录内存中的Web API服务]
p.
We illustrate these topics with code that you can
#[+liveExampleLink2('run live in a browser')].
p.
我们在#[+liveExampleLink2('在线版')]中展示了这些主题,你可以在浏览器中运行它们。
.l-main-section .l-main-section
h1 Demos :marked
# Demos
# 演示
h1 演示 This chapter describes server communication with the help of the following demos
本章通过下面这些演示,描述了服务端通讯的用法。
p This chapter describes server communication with the help of the following demos block demos-list
:marked
- [HTTP client: Tour of Heroes with Observables](#http-client)
- [HTTP客户端: 使用可观察对象的《英雄指南》](#http-client)
- [HTTP client: Tour of Heroes with !{_Promise}s](#promises)
- [HTTP客户端: 使用承诺的《英雄指南》](#promises)
- [JSONP client: Wikipedia to fetch data from a service that does not support CORS](#cors)
- [JSONP客户端: Wikipedia从一个不支持CORS的服务获取数据](#cors)
- [JSONP client: Wikipedia using observable operators to reduce server calls](#more-observables)
- [JSONP客户端: Wikipedia使用可观察对象的操作符减少服务端调用](#more-observables)
p 本章通过下面这些演示,描述了服务端通讯的用法。
ul
block demos-list
li #[a(href="#http-client") HTTP client: Tour of Heroes with Observables]
li #[a(href="#http-client") HTTP客户端: 使用可观察对象的《英雄指南》]
li #[a(href="#promises") HTTP client: Tour of Heroes with #{_Promise}s]
li #[a(href="#promises") HTTP客户端: 使用承诺的《英雄指南》]
li #[a(href="#cors") JSONP client: Wikipedia to fetch data from a service that does not support CORS]
li #[a(href="#cors") JSONP客户端: Wikipedia从一个不支持CORS的服务获取数据]
li #[a(href="#more-observables") JSONP client: Wikipedia using observable operators to reduce server calls]
li #[a(href="#more-observables") JSONP客户端: Wikipedia使用可观察对象的操作符减少服务端调用]
:marked :marked
These demos are orchestrated by the root `AppComponent` These demos are orchestrated by the root `AppComponent`
这些演示由根组件`AppComponent`统一演示。 这些演示由根组件`AppComponent`统一演示。
+makeExample('server-communication/ts/app/app.component.ts', null, 'app/app.component.ts') +makeExample('server-communication/ts/app/app.component.ts', null, 'app/app.component.ts')
block rxjs-import +ifDocsFor('ts')
:marked :marked
There is nothing remarkable here _except_ for the import of RxJS operators. There is nothing remarkable here _except_ for the import of RxJS operators.
@ -128,18 +134,18 @@ block rxjs-import
:marked :marked
First, we have to configure our application to use server communication facilities. First, we have to configure our application to use server communication facilities.
首先,我们必须配置应用程序,才能使用服务器通讯设施。 .l-main-section#http-providers
.l-main-section
h1#http-providers Providing HTTP Services
h1#http-providers 提供HTTP服务
:marked :marked
We use the !{_Angular_Http} client to communicate with a server using a familiar HTTP request/response protocol. # Providing HTTP Services
The `#{_Http}` client is one of a family of services in the !{_Angular_http_library}.
我们通过!{_Angular_Http}客户端使用熟悉的HTTP请求/回应协议与服务器通讯。`#{_Http}`客户端是!{_Angular_http_libraryCn}所提供的服务大家庭中的一员。 # 提供HTTP服务
block system-config-of-http
We use the !{_Angular_Http} client to communicate with a server using a familiar HTTP request/response protocol.
The `!{_Http}` client is one of a family of services in the !{_Angular_http_library}.
我们通过!{_Angular_Http}客户端使用熟悉的HTTP请求/回应协议与服务器通讯。`!{_Http}`客户端是!{_Angular_http_libraryCn}所提供的服务大家庭中的一员。
+ifDocsFor('ts')
.l-sub-section .l-sub-section
:marked :marked
SystemJS knows how to load services from the !{_Angular_http_library} when we import from the `@angular/http` module SystemJS knows how to load services from the !{_Angular_http_library} when we import from the `@angular/http` module
@ -157,8 +163,12 @@ block system-config-of-http
了解关于供应商的更多知识,参见[依赖注入](dependency-injection.html)一章。 了解关于供应商的更多知识,参见[依赖注入](dependency-injection.html)一章。
p In this demo, we register providers in the #[code bootstrap] method of #[code #[+adjExPath('app/main.ts')]]. :marked
p 在这个例子中,我们在#[code #[+adjExPath('app/main.ts')]]文件的#[code bootstrap]方法中注册供应商。 In this demo, we register providers in the `bootstrap()` method of
<span ngio-ex>app/main.ts</span>.
在这个例子中,我们在<span ngio-ex>app/main.ts</span>文件的`bootstrap()`方法中注册供应商。
+makeExample('server-communication/ts/app/main.ts', 'v1', 'app/main.ts (v1)')(format='.') +makeExample('server-communication/ts/app/main.ts', 'v1', 'app/main.ts (v1)')(format='.')
block http-providers block http-providers
@ -199,10 +209,12 @@ block http-providers
这种“偷梁换柱”的把戏是应用程序的根组件*不应该*察觉的。 这种“偷梁换柱”的把戏是应用程序的根组件*不应该*察觉的。
正因为这*一个*理由,我们把它藏在`main.ts`里,在层次上高于`AppComponent`。 正因为这*一个*理由,我们把它藏在`main.ts`里,在层次上高于`AppComponent`。
.l-main-section .l-main-section#http-client
h1#http-client The Tour of Heroes #[i HTTP] Client Demo
h1#http-client 《英雄指南》#[i HTTP]客户端的演示
:marked :marked
# The Tour of Heroes _HTTP_ Client Demo
# 《英雄指南》的HTTP客户端演示
Our first demo is a mini-version of the [tutorial](../tutorial)'s "Tour of Heroes" (ToH) application. Our first demo is a mini-version of the [tutorial](../tutorial)'s "Tour of Heroes" (ToH) application.
This version gets some heroes from the server, displays them in a list, lets us add new heroes, and saves them to the server. This version gets some heroes from the server, displays them in a list, lets us add new heroes, and saves them to the server.
We use the !{_Angular_Http} client to communicate via `XMLHttpRequest (XHR)`. We use the !{_Angular_Http} client to communicate via `XMLHttpRequest (XHR)`.
@ -308,11 +320,13 @@ block getheroes-and-addhero
关于组件的浅显讲解已经结束了,我们可以到`HeroService`的内部实现中看看。 关于组件的浅显讲解已经结束了,我们可以到`HeroService`的内部实现中看看。
.l-main-section
a#HeroService a#HeroService
h2#fetch-data Fetch data with the #[b HeroService] .l-main-section#fetch-data
h2#fetch-data 通过#[b HeroService]获取数据
:marked :marked
## Fetch data with the **HeroService**
## 通过**HeroService**获取数据
In many of our previous samples we faked the interaction with the server by In many of our previous samples we faked the interaction with the server by
returning mock heroes in a service like this one: returning mock heroes in a service like this one:
@ -332,9 +346,10 @@ h2#fetch-data 通过#[b HeroService]获取数据
注意,这个“!{_Angular_Http}客户端”服务[被注入](dependency-injection.html)到了`HeroService`的构造函数中。 注意,这个“!{_Angular_Http}客户端”服务[被注入](dependency-injection.html)到了`HeroService`的构造函数中。
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'ctor') +makeExample('server-communication/ts/app/toh/hero.service.ts', 'ctor')
:marked :marked
Look closely at how we call `#{_priv}http.get` Look closely at how we call `!{_priv}http.get`
仔细看看我们是如何调用`!{_priv}http.get`的
仔细看看我们是如何调用`#{_priv}http.get`的
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'http-get', 'app/toh/hero.service.ts (getHeroes)')(format=".") +makeExample('server-communication/ts/app/toh/hero.service.ts', 'http-get', 'app/toh/hero.service.ts (getHeroes)')(format=".")
:marked :marked
We pass the resource URL to `get` and it calls the server which should return heroes. We pass the resource URL to `get` and it calls the server which should return heroes.
@ -350,7 +365,7 @@ h2#fetch-data 通过#[b HeroService]获取数据
但目前,我们只能(临时性的)使用一个JSON文件来代替这个“内存Web API”。只要修改下服务器的URL就行了 但目前,我们只能(临时性的)使用一个JSON文件来代替这个“内存Web API”。只要修改下服务器的URL就行了
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json')(format=".") +makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json')(format=".")
block rxjs +ifDocsFor('ts')
:marked :marked
<a id="rxjs"></a> <a id="rxjs"></a>
The return value may surprise us. The return value may surprise us.
@ -455,9 +470,9 @@ a#extract-data
## 处理Response响应对象 ## 处理Response响应对象
Remember that our `getHeroes()` method mapped the `#{_priv}http.get` response object to heroes with an `#{_priv}extractData` helper method: Remember that our `getHeroes()` method mapped the `!{_priv}http.get` response object to heroes with an `!{_priv}extractData` helper method:
记住,`getHeroes()`借助一个`#{_priv}extractData`辅助方法来把`#{_priv}http.get`的响应对象映射成了英雄列表: 记住,`getHeroes()`借助一个`!{_priv}extractData`辅助方法来把`!{_priv}http.get`的响应对象映射成了英雄列表:
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'extract-data', 'app/toh/hero.service.ts (excerpt)')(format=".") +makeExample('server-communication/ts/app/toh/hero.service.ts', 'extract-data', 'app/toh/hero.service.ts (excerpt)')(format=".")
:marked :marked
The `response` object does not hold our data in a form we can use directly. The `response` object does not hold our data in a form we can use directly.
@ -490,7 +505,7 @@ block parse-json
.l-sub-section .l-sub-section
:marked :marked
We shouldn't expect the decoded JSON to be the heroes #{_array} directly. We shouldn't expect the decoded JSON to be the heroes !{_array} directly.
The server we're calling always wraps JSON results in an object with a `data` The server we're calling always wraps JSON results in an object with a `data`
property. We have to unwrap it to get the heroes. property. We have to unwrap it to get the heroes.
This is conventional web api behavior, driven by This is conventional web api behavior, driven by
@ -532,7 +547,7 @@ block parse-json
header HTTP的GET方法被推迟执行了 header HTTP的GET方法被推迟执行了
:marked :marked
The `#{_priv}http.get` does **not send the request just yet!** This observable is The `!{_priv}http.get` does **not send the request just yet!** This observable is
[*cold*](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md#cold-vs-hot-observables) [*cold*](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md#cold-vs-hot-observables)
which means the request won't go out until something *subscribes* to the observable. which means the request won't go out until something *subscribes* to the observable.
That *something* is the [HeroListComponent](#subscribe). That *something* is the [HeroListComponent](#subscribe).
@ -587,7 +602,7 @@ h4 #[b HeroListComponent] error handling
h4 #[b HeroListComponent] 错误处理 h4 #[b HeroListComponent] 错误处理
block hlc-error-handling block hlc-error-handling
:marked :marked
Back in the `HeroListComponent`, where we called `#{_priv}heroService.getHeroes()`, Back in the `HeroListComponent`, where we called `!{_priv}heroService.getHeroes()`,
we supply the `subscribe` function with a second function parameter to handle the error message. we supply the `subscribe` function with a second function parameter to handle the error message.
It sets an `errorMessage` variable which we've bound conditionally in the `HeroListComponent` template. It sets an `errorMessage` variable which we've bound conditionally in the `HeroListComponent` template.
@ -699,9 +714,9 @@ code-example(format="." language="javascript").
### JSON结果 ### JSON结果
As with `getHeroes()`, we [extract the data](#extract-data) from the response using the As with `getHeroes()`, we [extract the data](#extract-data) from the response using the
`#{_priv}extractData()` helper. `!{_priv}extractData()` helper.
像`getHeroes()`中一样,我们可以使用`#{_priv}extractData()`辅助函数从响应中[提取出数据](#extract-data)。 像`getHeroes()`中一样,我们可以使用`!{_priv}extractData()`辅助函数从响应中[提取出数据](#extract-data)。
block hero-list-comp-add-hero block hero-list-comp-add-hero
:marked :marked
@ -712,7 +727,7 @@ block hero-list-comp-add-hero
当有数据到来时,它就会把这个新的英雄对象追加(push)到`heroes`数组中,以展现给用户。 当有数据到来时,它就会把这个新的英雄对象追加(push)到`heroes`数组中,以展现给用户。
+makeExample('server-communication/ts/app/toh/hero-list.component.ts', 'addHero', 'app/toh/hero-list.component.ts (addHero)')(format=".") +makeExample('server-communication/ts/app/toh/hero-list.component.ts', 'addHero', 'app/toh/hero-list.component.ts (addHero)')(format=".")
block promises +ifDocsFor('ts')
h2#promises Fall back to Promises h2#promises Fall back to Promises
h2#promises 倒退为承诺(Promise) h2#promises 倒退为承诺(Promise)
@ -849,7 +864,7 @@ figure.image-display
block wikipedia-jsonp+ block wikipedia-jsonp+
:marked :marked
Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API. Let's use the latter for this example. Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API. Let's use the latter for this example.
The Angular `Jsonp` service both extends the `#{_Http}` service for JSONP and restricts us to `GET` requests. The Angular `Jsonp` service both extends the `!{_Http}` service for JSONP and restricts us to `GET` requests.
All other HTTP methods throw an error because JSONP is a read-only facility. All other HTTP methods throw an error because JSONP is a read-only facility.
Wikipedia提供了一个现代的`CORS` API和一个传统的`JSONP`搜索API。在这个例子中我们使用后者。 Wikipedia提供了一个现代的`CORS` API和一个传统的`JSONP`搜索API。在这个例子中我们使用后者。
@ -939,7 +954,7 @@ block wikipedia-jsonp+
该组件有一个`<input>`元素,它是用来从用户获取搜索关键词的*搜索框*。 该组件有一个`<input>`元素,它是用来从用户获取搜索关键词的*搜索框*。
在每次`keyup`事件被触发时,它调用`search(term)`方法。 在每次`keyup`事件被触发时,它调用`search(term)`方法。
The `search(term)` method delegates to our `WikipediaService` which returns an observable array of string results (`Observable<string[]`). The `search(term)` method delegates to our `WikipediaService` which returns an observable array of string results (`Observable<string[]>`).
Instead of subscribing to the observable inside the component as we did in the `HeroListComponent`, Instead of subscribing to the observable inside the component as we did in the `HeroListComponent`,
we forward the observable result to the template (via `items`) where the [async pipe](pipes.html#async-pipe) we forward the observable result to the template (via `items`) where the [async pipe](pipes.html#async-pipe)
in the `ngFor` handles the subscription. in the `ngFor` handles the subscription.
@ -1158,9 +1173,9 @@ a#in-mem-web-api
并且通过SystemJS(参见`systemjs.config.js`)把它注册进模块加载器。 并且通过SystemJS(参见`systemjs.config.js`)把它注册进模块加载器。
:marked :marked
The in-memory web API gets its data from #{_a_ca_class_with} a `createDb()` The in-memory web API gets its data from !{_a_ca_class_with} a `createDb()`
method that returns a map whose keys are collection names and whose values method that returns a map whose keys are collection names and whose values
are #{_array}s of objects in those collections. are !{_array}s of objects in those collections.
内存Web API从一个带有`createDb()`方法的自定义类中获取数据并且返回一个map它的主键(key)是一组名字,而值(value)是一组与之对应的对象数组。 内存Web API从一个带有`createDb()`方法的自定义类中获取数据并且返回一个map它的主键(key)是一组名字,而值(value)是一组与之对应的对象数组。
@ -1190,11 +1205,15 @@ block redirect-to-web-api
要想启用我们的服务模拟器我们通过Angular标准的“供应商注册”技术把默认的`XHRBackend`服务替换为了这个内存Web API服务。 要想启用我们的服务模拟器我们通过Angular标准的“供应商注册”技术把默认的`XHRBackend`服务替换为了这个内存Web API服务。
同时,我们使用来自模拟的英雄数据集的*种子数据*初始化了这个内存Web API。 同时,我们使用来自模拟的英雄数据集的*种子数据*初始化了这个内存Web API。
:marked
Here is the revised (and final) version of <span ngio-ex>app/main.ts></span> demonstrating these steps.
下面是修改过的(也是最终的)<span ngio-ex>app/main.ts></span>版本,用于演示这些步骤。
p Here is the revised (and final) version of the #[code #[+adjExPath('app/main.ts')]] demonstrating these steps. +makeExcerpt('app/main.ts', 'final')
p 下面是修改过的(也是最终的)#[code #[+adjExPath('app/main.ts')]]版本,用于演示这些步骤。 :marked
+makeExample('server-communication/ts/app/main.ts', 'final', 'app/main.ts (final)')(format=".") See the full source code in the <live-example></live-example>.
p See the full source code in the #[+liveExampleLink2()]. 要想查看完整的源代码,请参见<live-example></live-example>。
p 要想查看完整的源代码,参见#[+liveExampleLink2('浏览器中运行在线版')]。

View File

@ -26,8 +26,9 @@ block includes
- [write our own structural directive](#unless) - [write our own structural directive](#unless)
- [写我们自己的结构型指令](#unless) - [写我们自己的结构型指令](#unless)
p Try the #[+liveExampleLink2()]. Try the <live-example></live-example>.
p 试试#[+liveExampleLink2('在线例子')].
试试<live-example></live-example>。
<a id="definition"></a> <a id="definition"></a>
.l-main-section .l-main-section

View File

@ -63,8 +63,7 @@ block includes
* [safe navigation operator (?.)](#safe-navigation-operator) * [safe navigation operator (?.)](#safe-navigation-operator)
* [“安全导航操作符”(?.)](#safe-navigation-operator) * [“安全导航操作符”(?.)](#safe-navigation-operator)
p. The <live-example></live-example>
The #[+liveExampleLink2()]
demonstrates all of the syntax and code snippets described in this chapter. demonstrates all of the syntax and code snippets described in this chapter.
p. p.
这个#[+liveExampleLink2('在线例子')]演示了本章中描述的所有语法和代码片段。 这个#[+liveExampleLink2('在线例子')]演示了本章中描述的所有语法和代码片段。

View File

@ -27,25 +27,30 @@ block includes
虽然我们正在用#{_Lang},但你也可以用#{_docsFor == 'ts' ? 'Dart' : 'TypeScript'}和JavaScript来写Angular 2应用。 虽然我们正在用#{_Lang},但你也可以用#{_docsFor == 'ts' ? 'Dart' : 'TypeScript'}和JavaScript来写Angular 2应用。
只要从Banner区的下拉框选择想用的那种语言就可以了。 只要从Banner区的下拉框选择想用的那种语言就可以了。
h1 Try it! :marked
h1 试试! # Try it!
p
| Try the #[+liveExampleLink2()] which loads the sample app # 试试
+ifDocsFor('ts')
| &nbsp;in #[a(href="http://plnkr.co/" title="Plunker" target="_blank") plunker] Try the <live-example></live-example> which loads the sample app
| &nbsp;and displays the simple message: <span if-docs="ts">
p in <a href="http://plnkr.co/" title="Plunker" target="_blank">plunker</a>
| 试试#[+liveExampleLink2('在线范例', 'quickstart')],它将把此范例加载 </span>
+ifDocsFor('ts') and displays the simple message:
| &nbsp;到 #[a(href="http://plnkr.co/" title="Plunker" target="_blank") plunker]中
| &nbsp;并显示一条简单的消息: 试试这个<live-example></live-example>,它将把此范例加载到
<span if-docs="ts">
<a href="http://plnkr.co/" title="Plunker" target="_blank">plunker</a>中
</span>
,并显示一条简单的消息:
figure.image-display figure.image-display
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="“快速起步”应用的输出") img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="“快速起步”应用的输出")
h1 Build this app!
h1 构建此应用!
:marked :marked
# Build this app!
# 构建此应用!
- [Prerequisite](#prereq): Install #{_prereq} - [Prerequisite](#prereq): Install #{_prereq}
- [环境准备](#prereq): 安装#{_prereq} - [环境准备](#prereq): 安装#{_prereq}
- [Step 1](#create-and-configure): Create the apps project folder and - [Step 1](#create-and-configure): Create the apps project folder and
@ -53,8 +58,8 @@ h1 构建此应用!
- [步骤1](#create-and-configure):创建本应用的项目文件夹,并且定义包的依赖以及特别的项目设置。 - [步骤1](#create-and-configure):创建本应用的项目文件夹,并且定义包的依赖以及特别的项目设置。
- [Step 2](#root-component): Create the apps Angular root component - [Step 2](#root-component): Create the apps Angular root component
- [步骤2](#root-component): 创建本应用的Angular根组件 - [步骤2](#root-component): 创建本应用的Angular根组件
- [Step 3](#main): Add `main.#{_docsFor}`, identifying the root component to Angular - [Step 3](#main): Add <span ngio-ex>main.ts</span>, identifying the root component to Angular
- [步骤3](#main):添加`main.#{_docsFor}`用来告诉Angular哪个是根组件。 - [步骤3](#main):添加<span ngio-ex>main.ts</span>用来告诉Angular哪个是根组件。
- [Step 4](#index): Add `index.html`, the web page that hosts the application - [Step 4](#index): Add `index.html`, the web page that hosts the application
- [步骤4](#index):添加`index.html`,本应用的宿主页面。 - [步骤4](#index):添加`index.html`,本应用的宿主页面。
- [Step 5](#build-and-run): Build and run the app - [Step 5](#build-and-run): Build and run the app
@ -76,7 +81,7 @@ block setup-tooling
如果你的机器上还没有**[Node.js®和npm](https://nodejs.org/en/download/)**,请安装它们。 如果你的机器上还没有**[Node.js®和npm](https://nodejs.org/en/download/)**,请安装它们。
.l-sub-section .l-sub-section
:marked :marked
**Verify that you are running at least node `v5.x.x` and npm `3.x.x`** **Verify that you are running at least node `v4.x.x` and npm `3.x.x`**
by running `node -v` and `npm -v` in a terminal/console window. by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors. Older versions produce errors.
@ -516,15 +521,15 @@ block create-main
让[SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)更加容易。 让[SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)更加容易。
要达成这些目标,我们需要从其它库中引入一个不同类型的`bootstrap`函数。 要达成这些目标,我们需要从其它库中引入一个不同类型的`bootstrap`函数。
### Why create separate *main.#{_docsFor}* and app component files? ### Why create separate *<span ngio-ex>main.ts</span>* and app component files?
### 为什么创建一个分离的*main.#{_docsFor}*文件和应用组件文件? ### 为什么创建一个分离的*<span ngio-ex>main.ts</span>*文件和应用组件文件?
Both `main.#{_docsFor}` and the app component files are tiny. Both <span ngio-ex>main.ts</span> and the app component files are tiny.
This is just a QuickStart. This is just a QuickStart.
We could have merged these two files into one We could have merged these two files into one
and spared ourselves some complexity. and spared ourselves some complexity.
无论是`main.#{_docsFor}`还是组件的文件都非常小。 无论是<span ngio-ex>main.ts</span>还是组件的文件都非常小。
它只是一个“快速起步”而已。 它只是一个“快速起步”而已。
我们本可以把这两个文件装进`app.component`文件来减少一点复杂度。 我们本可以把这两个文件装进`app.component`文件来减少一点复杂度。
@ -728,7 +733,7 @@ h2#index 步骤4添加#[code index.html]
a(id="my-app") a(id="my-app")
:marked :marked
When Angular calls the `bootstrap` function in `main.#{_docsFor}`, it reads the `AppComponent` When Angular calls the `bootstrap` function in <span ngio-ex>main.ts</span>, it reads the `AppComponent`
metadata, finds the `my-app` selector, locates an element tag named `my-app`, metadata, finds the `my-app` selector, locates an element tag named `my-app`,
and renders our application's view between those tags. and renders our application's view between those tags.

View File

@ -43,13 +43,13 @@ include ../_util-fns
我们将学习足够的Angular核心技术来作为起步并建立信心 —— 证明Angular确实能做到我们想让它做的。 我们将学习足够的Angular核心技术来作为起步并建立信心 —— 证明Angular确实能做到我们想让它做的。
虽然我们将覆盖大部分“简介级”知识,但还是会放上大量链接,指向更深入的章节。 虽然我们将覆盖大部分“简介级”知识,但还是会放上大量链接,指向更深入的章节。
Run the <live-example name="toh-6"></live-example>.
运行<live-example name="toh-6"></live-example>。
// #enddocregion intro // #enddocregion intro
p Run the #[+liveExampleLink2('', 'toh-6')].
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-6')]。
// #docregion main // #docregion main
.l-main-section .l-main-section
:marked :marked

View File

@ -9,11 +9,10 @@ include ../_util-fns
每一个故事,都有一个起点。而我们的故事则开始于[“快速起步”](../quickstart.html)的结尾处。 每一个故事,都有一个起点。而我们的故事则开始于[“快速起步”](../quickstart.html)的结尾处。
p Run the #[+liveExampleLink2('', 'toh-1')] for this part. Run the <live-example></live-example> for this part.
运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-1')]。
:marked
Create a folder called `angular2-tour-of-heroes` and follow the [QuickStart](../quickstart.html) steps Create a folder called `angular2-tour-of-heroes` and follow the [QuickStart](../quickstart.html) steps
which provide the prerequisites, the folder structure, and the core files for our Tour of Heroes. which provide the prerequisites, the folder structure, and the core files for our Tour of Heroes.
@ -285,11 +284,10 @@ code-example(language="html").
* 通过`ngModel`指令,这些修改还影响到了每一个对`hero.name`的其它绑定。 * 通过`ngModel`指令,这些修改还影响到了每一个对`hero.name`的其它绑定。
p Run the #[+liveExampleLink2('', 'toh-1')] for this part. Run the <live-example></live-example> for this part.
运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-1')]。
:marked
Here's the complete `app.component.ts` as it stands now: Here's the complete `app.component.ts` as it stands now:
完整的`app.component.ts`是这样的: 完整的`app.component.ts`是这样的:

View File

@ -9,13 +9,10 @@ include ../_util-fns
Well expand our Tour of Heroes app to display a list of heroes, Well expand our Tour of Heroes app to display a list of heroes,
allow the user to select a hero, and display the heros details. allow the user to select a hero, and display the heros details.
我们的故事需要更多的英雄了。我们将扩展这个《英雄指南》,来显示一个英雄列表,允许用户选择一个英雄,并且显示英雄的详情。 Run the <live-example></live-example> for this part.
运行这部分的<live-example></live-example>。
p Run the #[+liveExampleLink2('', 'toh-2')] for this part.
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-2')]。
:marked
Lets take stock of what well need to display a list of heroes. Lets take stock of what well need to display a list of heroes.
First, we need a list of heroes. We want to display those heroes in the views template, First, we need a list of heroes. We want to display those heroes in the views template,
so well need a way to do that. so well need a way to do that.
@ -524,11 +521,10 @@ code-example(language="bash").
* 我们学会了如何在组件模板中使用内建的`ngIf`和`ngFor`指令 * 我们学会了如何在组件模板中使用内建的`ngIf`和`ngFor`指令
p Run the #[+liveExampleLink2('', 'toh-2')] for this part. Run the <live-example></live-example> for this part.
运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-2')]。
:marked
### The Road Ahead ### The Road Ahead
### 前方的路 ### 前方的路

View File

@ -4,10 +4,9 @@ include ../_util-fns
Our app is growing. Our app is growing.
Use cases are flowing in for reusing components, passing data to components, and creating more reusable assets. Let's separate the heroes list from the hero details and make the details component reusable. Use cases are flowing in for reusing components, passing data to components, and creating more reusable assets. Let's separate the heroes list from the hero details and make the details component reusable.
我们的应用继续成长。 Run the <live-example></live-example> for this part.
这次的例子将依次展示:复用组件、给组件传入数据以及创建更容易复用的软件资产。我们先把英雄列表从英雄详情中分离出来,并且让详情组件可复用。
p Run the #[+liveExampleLink2('', 'toh-3')] for this part. 运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-3')]。 p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-3')]。
@ -418,7 +417,7 @@ code-example(format=".").
* 我们学会了在`directives`中定义应用所需的指令。 * 我们学会了在`directives`中定义应用所需的指令。
p Run the #[+liveExampleLink2('', 'toh-3')] for this part. Run the <live-example></live-example> for this part.
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-3')]。 p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-3')]。

View File

@ -26,11 +26,9 @@ include ../_util-fns
Because data services are invariably asynchronous, Because data services are invariably asynchronous,
we'll finish the chapter with a **!{_Promise}**-based version of the data service. we'll finish the chapter with a **!{_Promise}**-based version of the data service.
因为数据服务通常都是异步的,所以在本章的最后,我们会把它重构为基于承诺(Promise一种异步编程模式)的版本。 Run the <live-example></live-example> for this part.
p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-4')] 运行这部分的<live-example></live-example>。
.l-main-section .l-main-section
:marked :marked
@ -654,11 +652,10 @@ a#child-component
* 我们把服务改造为返回承诺的,并让组件从承诺获取数据。 * 我们把服务改造为返回承诺的,并让组件从承诺获取数据。
p Run the #[+liveExampleLink2('', 'toh-4')] for this part. Run the <live-example></live-example> for this part.
运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-4')]。
:marked
### The Road Ahead ### The Road Ahead
### 前方的路 ### 前方的路

View File

@ -41,11 +41,10 @@ figure.image-display
The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail
than we will in this tutorial. than we will in this tutorial.
[路由与导航](../guide/router.html)一章覆盖了比该教程中更详细的路由知识。 :marked
Run the <live-example></live-example> for this part.
p Run the #[+liveExampleLink2('', 'toh-5')] for this part.
运行这部分的<live-example></live-example>。
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-5')]。
.l-sub-section .l-sub-section
img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="弹出窗口" align="right" style="margin-right:-20px") img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="弹出窗口" align="right" style="margin-right:-20px")
@ -1331,18 +1330,15 @@ figure.image-display
.l-main-section .l-main-section
:marked :marked
## Application structure and code ## Application structure and code
## 应用结构和代码 ## 应用结构和代码
p. Review the sample source code in the <live-example></live-example> for this chapter.
Review the sample source code in the #[+liveExampleLink2('', 'toh-5')] for this chapter.
Verify that we have the following structure: Verify that we have the following structure:
在<live-example></live-example>中回顾本章的范例代码。
验证我们是否已经得到了如下结构:
p.
在#[+liveExampleLink2('在线例子', 'toh-5')]中回顾这部分代码。
验证我们是否已经得到了下列结构:
:marked
.filetree .filetree
.file angular2-tour-of-heroes .file angular2-tour-of-heroes
.children .children

View File

@ -24,7 +24,7 @@ block includes
在这一章中我们要让应用程序学会通过HTTP调用来访问远程服务器上相应的Web API。 在这一章中我们要让应用程序学会通过HTTP调用来访问远程服务器上相应的Web API。
p Run the #[+liveExampleLink2('', 'toh-6')] for this part. Run the <live-example></live-example> for this part.
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-6')]。 p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-6')]。
@ -91,7 +91,7 @@ block http-providers
:marked :marked
We should be able to access `!{_Http}` services from anywhere in the application. We should be able to access `!{_Http}` services from anywhere in the application.
So we register them in the `bootstrap` call of `main.!{_docsFor}` where we So we register them in the `bootstrap` call of <span ngio-ex>main.ts</span> where we
launch the application and its root `AppComponent`. launch the application and its root `AppComponent`.
我们要能从本应用的任何地方访问这些服务,所以,就要在`main.ts`中的`bootstrap`方法中注册它们。 我们要能从本应用的任何地方访问这些服务,所以,就要在`main.ts`中的`bootstrap`方法中注册它们。
@ -604,14 +604,13 @@ block review
:marked :marked
## Application structure and code ## Application structure and code
### 回顾应用结构 ## 应用结构与代码
p. Review the sample source code in the <live-example></live-example> for this chapter.
Review the sample source code in the #[+liveExampleLink2('', 'toh-6')] for this chapter.
Verify that we have the following structure: Verify that we have the following structure:
p. 在<live-example></live-example>中回顾本章的范例代码。
在#[+liveExampleLink2('', 'toh-6')]中回顾本章的范例代码,验证是否得到了如下结构: 验证我们是否得到了如下结构:
block filetree block filetree
.filetree .filetree

View File

@ -0,0 +1,25 @@
/*
* Angular.io Example Conditional Directive
*
* Usage:
* <tag if-docs="ts|dart">...</tag>
*
* This is equivalent to an ngIf that holds if this containing
* docs are for TypeScript.
*/
angularIO.directive('ifDocs', ['ngIfDirective', '$location', function (ngIfDirective, $location) {
var ngIf = ngIfDirective[0];
return {
transclude: ngIf.transclude,
priority: ngIf.priority,
terminal: ngIf.terminal,
restrict: ngIf.restrict,
link: function (scope, element, attrs) {
var ngIfCond = (attrs.ifDocs === 'dart') == !NgIoUtil.isDartDoc($location);
attrs.ngIf = function () { return !ngIfCond; }
ngIf.link.apply(ngIf, arguments);
}
};
}]);

View File

@ -0,0 +1,54 @@
/*
* Angular.io Live Example Directive
*
* Renders a link to a live/host example of the doc chapter
* app this directive is contained in.
*
* Usage:
* <live-example [name="..."] [noSource] [srcText="..."]>text</live-example>
* Example:
* <p>Run <live-example name="toh-1">this chapter's example</live-example></p>.
*/
angularIO.directive('liveExample', ['$location', function ($location) {
function a(text, attrs) {
var attr = (attrs.href ? ' href="' + attrs.href + '"' : '') +
(attrs.target ? ' target="' + attrs.target + '"' : '');
return '<a' + attr + '>' + text + '</a>';
}
function span(text) { return '<span>' + text + '</span>'; }
return {
restrict: 'E',
compile: function (tElement, attrs) {
var text = tElement.text() || 'live example';
var ex = attrs.name || NgIoUtil.getExampleName($location);
var href, template;
var isForDart = attrs.lang === 'dart' || NgIoUtil.isDartDoc($location);
var href = isForDart
? 'http://angular-examples.github.io/' + ex
: '/resources/live-examples/' + ex + '/ts/plnkr.html';
// Link to live example.
var template = a(text, { href: href, target: '_blank' });
// The hosted example and sources are in different locations for Dart.
// Also show link to sources for Dart, unless noSource is specified.
if (isForDart && !attrs.hasOwnProperty('nosource')) {
var srcText = attrs.srcText || 'view source';
var srcHref = 'http://github.com/angular-examples/' + ex;
template = span(template + ' (' + a(srcText, { href: srcHref, target: '_blank' }) + ')');
}
// UPDATE ELEMENT WITH NEW TEMPLATE
tElement.html(template);
// RETURN ELEMENT
return function (scope, element, attrs) { };
}
};
}]);

View File

@ -0,0 +1,38 @@
/*
* Angular.io Example File Path Directive
*
* Usage:
* <span ngio-ex [lang="ts|dart"]>some_path</span>
* <ngio-ex path="some_path" [lang="ts|dart"]></ngio-ex>
*
* The latter gets treated as a block tag in markdown when at the start of a line.
*
* Yields
* <code>some_path_possibly_adjusted</code>
*
* The given path is assumed to be a TS app directory or
* source file path. When this directive is used in Dart docs
* it adjusts the path to conform to Dart directory and file
* name conventions. See NgIoUtil.adjustTsExamplePathForDart()
* for details.
*/
angularIO.directive('ngioEx', ['$location', function ($location) {
return {
restrict: 'AE',
compile: function (tElement, attrs) {
var examplePath = attrs.path || tElement.text();
if (NgIoUtil.isDartDoc($location) || attrs.lang === 'dart') {
examplePath = NgIoUtil.adjustTsExamplePathForDart(examplePath);
}
var template = '<code>' + examplePath + '</code>';
// UPDATE ELEMENT WITH NEW TEMPLATE
tElement.html(template);
// RETURN ELEMENT
return function (scope, element, attrs) { };
}
};
}]);

View File

@ -0,0 +1,87 @@
// This will be nicer once we switch to Ng2. For now, define a singleton.
var NgIoUtil = (function () {
function NgIoUtil() { }
NgIoUtil.isDartDoc = function ($location) {
var loc = $location.absUrl();
return loc.includes('/docs/dart/');
};
// The following util functions are adapted from _utils-fn.jade.
// Note that basename(), etc doesn't quite follow
// https://nodejs.org/api/path.html
// but it suits our purpose for now.
NgIoUtil.adjustTsExamplePathForDart = function (_path) {
/* Convert a TS example path into a Dart example path. E.g.,
*
* - app/main.ts -> web/main.dart
* - displaying-data/ts/app/app.component.2.ts -> displaying-data/dart/lib/app_component.dart
*
* Notice that the '.2' is dropped from the name.
*/
if (!_path) return _path;
var path = _path.trim();
var folder = NgIoUtil.folderName(path);
var ext = NgIoUtil.extname(path);
var baseNameNoExt = NgIoUtil.basename(path, ext);
var inWebFolder = baseNameNoExt.match(/^(main|index)(\.\d)?$/);
// Adjust the folder path, e.g., '/ts/' -> '/dart/'
folder = folder
.replace(/(^|\/)ts($|\/)/, '$1dart$2')
.replace(/(^|\/)app($|\/)/, inWebFolder ? '$1web$2' : '$1lib$2');
// Special case not handled above: e.g., index.html -> web/index.html
if (baseNameNoExt.match(/^(index|styles)(\.\d)?$/) && !folder.match(/web$/))
folder = (folder ? folder + '/' : '') + 'web';
// In file name, replace special characters with underscore
baseNameNoExt = baseNameNoExt.replace(/[\-\.]/g, '_');
// Adjust the file extension
if (ext == '.ts') ext = '.dart';
return (folder ? folder + '/' : '') + baseNameNoExt + ext;
};
NgIoUtil.extname = function (path) {
var i = path.lastIndexOf('.');
return i > 0 ? path.substr(i) : '';
};
NgIoUtil.basename = function (path, optExt) {
var i = path.lastIndexOf('/');
var name = i > 0 ? path.substr(i + 1) : path;
if (optExt) name = name.substr(0, name.length - optExt.length);
return name;
};
NgIoUtil.folderName = function (path) {
var i = path.lastIndexOf('/');
return i > 0 ? path.substr(0, i) : '';
};
NgIoUtil._exampleName = ''; // example name is unique to a page; e.g., toh-1
NgIoUtil.setExampleName = function (name) {
// Adjust name for known cases where chapter name is not the example name.
var matches = name.match(/(toh-)pt(\d+)/);
if (matches) name = matches[1] + matches[2];
NgIoUtil._exampleName = name;
}
NgIoUtil.getExampleName = function ($location) {
if (!NgIoUtil._exampleName) {
// TODO: use $location.path() instead(?). It seems to be empty.
var loc = $location.absUrl();
// E.g., https://example.com/docs/dart/latest/guide/displaying-data.html
var matches = loc.match(/.*\/([\w\.\-]+)\.html/);
if (matches) NgIoUtil.setExampleName(matches[1]); // cache name
}
return NgIoUtil._exampleName;
};
return NgIoUtil;
} ());

View File

@ -76,7 +76,7 @@ div(layout="row" layout-xs="column" class="row-margin ng-cloak")
div(flex="80" flex-xs="100") div(flex="80" flex-xs="100")
{%- for decorator in doc.decorators %} {%- for decorator in doc.decorators %}
pre.prettyprint.no-bg pre.prettyprint.no-bg
code(class="api-doc-code") code(class="api-doc-code").
@{$ decorator.name $}{$ paramList(decorator.arguments) | indent(10, false) $} @{$ decorator.name $}{$ paramList(decorator.arguments) | indent(10, false) $}
:marked :marked
{%- if not decorator.notYetDocumented %} {%- if not decorator.notYetDocumented %}