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:
commit
0303a18020
|
@ -17,13 +17,13 @@ env:
|
|||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true"
|
||||
- env: "SCRIPT=\"run-e2e-tests --fast\" PREVIEW=true"
|
||||
before_install:
|
||||
- npm install -g gulp --no-optional
|
||||
before_script:
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
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
|
||||
script:
|
||||
- gulp $SCRIPT
|
||||
|
|
|
@ -22,6 +22,7 @@ script(src="/resources/js/vendor/angular-material.min.js")
|
|||
<!-- Angular.io Site JS -->
|
||||
script(src="/translate/cn/translate.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/resources-controller.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-pane.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")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// #docregion
|
||||
// #docregion first, final
|
||||
import { Component } from '@angular/core';
|
||||
import { NgForm } from '@angular/common';
|
||||
import { NgForm } from '@angular/forms';
|
||||
|
||||
import { Hero } from './hero';
|
||||
|
||||
|
|
|
@ -20,12 +20,14 @@ include ../../../_includes/_util-fns
|
|||
- var _indexHtmlDir = 'web';
|
||||
- var _mainDir = 'web';
|
||||
|
||||
//- Deprecated
|
||||
mixin liveExampleLink(linkText, exampleUrlPartName)
|
||||
- var text = linkText || '在线例子';
|
||||
- var ex = exampleUrlPartName || getExampleName();
|
||||
- var href = 'http://angular-examples.github.io/' + ex;
|
||||
a(href='#{href}' target="_blank")= text
|
||||
|
||||
//- Deprecated
|
||||
mixin liveExampleLink2(linkText, exampleUrlPartName)
|
||||
- var srcText = attributes.srcText || '查看源码';
|
||||
- var ex = exampleUrlPartName || attributes.example || getExampleName();
|
||||
|
|
|
@ -10,21 +10,12 @@ block ctor-syntax
|
|||
We also leveraged Dart's constructor syntax for declaring parameters and
|
||||
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
|
||||
//- 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
|
||||
//- identified as targets for static code generation. Generally this is achieved
|
||||
//- by marking the class as @Injectable (though there are other mechanisms).
|
||||
|
||||
block ts-any-decorator-will-do
|
||||
//- N/A
|
||||
|
||||
block always-include-paren
|
||||
:marked
|
||||
Always write `@Injectable()`, not just `@Injectable`.
|
||||
|
@ -43,11 +34,6 @@ block real-logger
|
|||
A real implementation would probably use the
|
||||
[logging package](https://pub.dartlang.org/packages/logging).
|
||||
|
||||
block canonical-provider-expr
|
||||
| that creates a new instance of the
|
||||
a(href="../api/core/Provider-class.html") Provider
|
||||
| class:
|
||||
|
||||
block provider-ctor-args
|
||||
- var _secondParam = 'named parameter, such as <code>useClass</code>'
|
||||
:marked
|
||||
|
|
|
@ -8,16 +8,9 @@ block includes
|
|||
- var _Angular_http_library = 'Dart <a href="' + _httpUrl + '"><b>http</b></a> library'
|
||||
|
||||
block demos-list
|
||||
li #[a(href="#http-client") HTTP client: Tour of Heroes]
|
||||
li #[a(href="#cors") JSONP client: Wikipedia to fetch data from a service that does not support CORS] #[b (under development)]
|
||||
|
||||
block rxjs-import
|
||||
//- N/A
|
||||
|
||||
block http-client
|
||||
|
||||
block system-config-of-http
|
||||
//- N/A
|
||||
:marked
|
||||
- [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 http-providers
|
||||
:marked
|
||||
|
@ -50,9 +43,6 @@ block getheroes-and-addhero
|
|||
programming in Dart, or the tutorial on
|
||||
[_Asynchronous Programming: Futures_](https://www.dartlang.org/docs/tutorials/futures/).
|
||||
|
||||
block rxjs
|
||||
//- N/A
|
||||
|
||||
block parse-json
|
||||
:marked
|
||||
The response data are in JSON string form.
|
||||
|
@ -65,7 +55,7 @@ block error-handling
|
|||
block hlc-error-handling
|
||||
:marked
|
||||
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 — which we've bound conditionally in the
|
||||
template — 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,
|
||||
the new hero is added to the `heroes` list for presentation to the user.
|
||||
|
||||
block promises
|
||||
//- N/A
|
||||
|
||||
block wikipedia-jsonp+
|
||||
:marked
|
||||
Wikipedia offers a modern `CORS` API and a legacy `JSONP` search API.
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
include ../_util-fns
|
||||
|
||||
+includeShared('{ts}', 'intro')
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-5')].
|
||||
|
||||
+includeShared('{ts}', 'main')
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ include ../_util-fns
|
|||
|
||||
.callout.is-helpful
|
||||
header Source code
|
||||
p Run the #[+liveExampleLink2('', 'toh-1')] for this part.
|
||||
:marked
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
:marked
|
||||
## Keep the app compiling and running
|
||||
|
|
|
@ -6,8 +6,8 @@ include ../_util-fns
|
|||
We’ll expand our Tour of Heroes app to display a list of heroes,
|
||||
allow the user to select a hero, and display the hero’s details.
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-2')] for this part.
|
||||
:marked
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
Let’s take stock of what we’ll need to display a list of heroes.
|
||||
First, we need a list of heroes. We want to display those heroes in the view’s template,
|
||||
so we’ll 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 hero’s details
|
||||
* We learned how to use the built-in directives `ngIf` and `ngFor` in a component’s template
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-2')] for this part.
|
||||
:marked
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
### The Road Ahead
|
||||
Our Tour of Heroes has grown, but it’s far from complete.
|
||||
We can't put the entire app into a single component.
|
||||
|
|
|
@ -4,7 +4,7 @@ include ../_util-fns
|
|||
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.
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-3')] for this part.
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -240,7 +240,7 @@ code-example(format=".")
|
|||
* We learned to bind a parent component to a child component.
|
||||
* 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
|
||||
:marked
|
||||
|
|
|
@ -15,7 +15,7 @@ include ../_util-fns
|
|||
Because data services are invariably asynchronous,
|
||||
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
|
||||
:marked
|
||||
|
|
|
@ -18,7 +18,7 @@ figure.image-display
|
|||
The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail
|
||||
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
|
||||
:marked
|
||||
|
@ -653,11 +653,10 @@ figure.image-display
|
|||
.l-main-section
|
||||
:marked
|
||||
## 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:
|
||||
|
||||
:marked
|
||||
.filetree
|
||||
.file angular2_tour_of_heroes
|
||||
.children
|
||||
|
|
|
@ -4,12 +4,14 @@ include ../../../_includes/_util-fns
|
|||
- var _docsFor = 'ts';
|
||||
//- Other values match the defaults.
|
||||
|
||||
//- Deprecated
|
||||
mixin liveExampleLink(linkText, exampleUrlPartName)
|
||||
- var text = linkText || 'live example';
|
||||
- var ex = exampleUrlPartName || getExampleName();
|
||||
- var href = '/resources/live-examples/' + ex + '/ts/plnkr.html';
|
||||
a(href='#{href}' target="_blank")= text
|
||||
|
||||
//- Deprecated
|
||||
mixin liveExampleLink2(linkText, exampleUrlPartName)
|
||||
//- In Dart this gives 2 links: to the demo and to the source.
|
||||
+liveExampleLink(linkText, exampleUrlPartName)
|
||||
|
|
|
@ -33,7 +33,7 @@ h2#devenv Step 1. Set up the Development Environment
|
|||
if they are not already on your machine.
|
||||
.l-sub-section
|
||||
: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.
|
||||
Older versions produce errors.
|
||||
:marked
|
||||
|
|
|
@ -19,10 +19,9 @@ block includes
|
|||
* [pass values into the directive using data binding](#bindings)
|
||||
* [使用数据绑定把值传到指令中](#bindings)
|
||||
|
||||
p Try the #[+liveExampleLink2()].
|
||||
p 试用#[+liveExampleLink2("在线例子")]。
|
||||
Try the <live-example></live-example>.
|
||||
试试<live-example></live-example>。
|
||||
|
||||
:marked
|
||||
## Directives overview
|
||||
## 指令概览
|
||||
|
||||
|
|
|
@ -33,8 +33,9 @@ block includes
|
|||
* [Appendix 2: Loading Styles with Relative URLs](#relative-urls)
|
||||
* [附录2:使用相对URL加载样式](#relative-urls)
|
||||
|
||||
p Run the #[+liveExampleLink2()] of the code shown in this chapter.
|
||||
p 运行本章这些代码的#[+liveExampleLink2("在线例子")]
|
||||
Run the <live-example></live-example> of the code shown in this chapter.
|
||||
|
||||
运行本章这些代码的<live-example></live-example>。
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
|
|
@ -29,8 +29,9 @@ block includes
|
|||
- [Summary](#summary)
|
||||
- [总结](#summary)
|
||||
|
||||
p Run the #[+liveExampleLink2()].
|
||||
p 运行#[+liveExampleLink2('在线例子')].
|
||||
Run the <live-example></live-example>.
|
||||
|
||||
运行<live-example></live-example>.
|
||||
|
||||
.l-main-section#why-di
|
||||
:marked
|
||||
|
@ -658,10 +659,6 @@ 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`一样,我们一会儿将会学到)
|
||||
是一个<a href="#{injMetaUrl}">InjectableMetadata</a>的子类型。实际上,`InjectableMetadata`装饰器标识着一个类是注入器实例化的目标。
|
||||
|
||||
|
||||
block ts-any-decorator-will-do
|
||||
.l-sub-section
|
||||
: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.
|
||||
- var __andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> object literal';
|
||||
- var __andProvideFn = _docsFor == 'dart' ? '' : '和 <i>provide</i> 对象';
|
||||
#provide
|
||||
:marked
|
||||
### *Provider* 类!{__andProvideFn}
|
||||
### The *Provider* class !{__andProvideFn}
|
||||
|
||||
:marked
|
||||
We wrote the `providers` #{_array} like this:
|
||||
|
||||
|
@ -813,8 +810,6 @@ p
|
|||
| This is actually a short-hand expression for a provider registration
|
||||
block canonical-provider-expr
|
||||
| using a <i>provider</i> object literal with two properties:
|
||||
p
|
||||
| 这实际上是用_provider_对象的字面量注册供应商的缩写表达式。
|
||||
|
||||
+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
|
||||
must acquire services generically and dynamically.
|
||||
|
||||
框架的开发人员可能会需要此方法 —— 当他们不得不以通用和动态的方式获取服务时。
|
||||
// #enddocregion appendix-explicit-injector-2
|
||||
|
||||
block one-class-per-file-ts-tradeoffs
|
||||
.l-main-section#one-class-per-file
|
||||
:marked
|
||||
|
|
|
@ -21,8 +21,9 @@ block includes
|
|||
|
||||
在本章中,我们将浏览这些要点,并写点代码来验证它。
|
||||
|
||||
p Try the #[+liveExampleLink2()].
|
||||
p 试试#[+liveExampleLink2("在线例子")].
|
||||
Try the <live-example></live-example>.
|
||||
|
||||
试试<live-example></live-example>.
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
|
|
@ -62,7 +62,7 @@ block includes
|
|||
|
||||
* [AfterContentInit和AfterContentChecked](#aftercontent)
|
||||
|
||||
p Try the #[+liveExampleLink2()].
|
||||
Try the <live-example></live-example>.
|
||||
|
||||
p 试一试#[+liveExampleLink2('在线例子')]。
|
||||
|
||||
|
@ -327,18 +327,19 @@ a(id="other-lifecycles")
|
|||
|
||||
第三方库也可能会实现它们自己的钩子,以便让我们这些开发者在使用时能做更多的控制。
|
||||
|
||||
a#the-sample
|
||||
.l-main-section
|
||||
h2 Lifecycle exercises
|
||||
h2 生命周期练习
|
||||
p.
|
||||
The #[+liveExampleLink()]
|
||||
.l-main-section#the-sample
|
||||
:marked
|
||||
## Lifecycle exercises
|
||||
|
||||
## 生命周期练习
|
||||
|
||||
The <live-example></live-example>
|
||||
demonstrates the lifecycle hooks in action through a series of exercises
|
||||
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
|
||||
a *child* component that illustrates one or more of the lifecycle hook methods.
|
||||
|
||||
|
|
|
@ -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>!
|
||||
|
||||
**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.
|
||||
Older versions produce errors.
|
||||
|
||||
|
|
|
@ -23,16 +23,11 @@ block includes
|
|||
We almost think of them as 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!
|
||||
Try the #[+liveExampleLink2()].
|
||||
Try the <live-example></live-example>.
|
||||
|
||||
p.
|
||||
欢迎来到Angular“管道(Pipe)”的世界!我们可以把这种简单的“值-显示”转换器声明在HTML中。
|
||||
试试#[+liveExampleLink2('在线例子')].
|
||||
试试<live-example></live-example>。
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
@ -258,18 +253,14 @@ figure.image-display
|
|||
Angular built-in pipes are pre-registered.
|
||||
Custom pipes must be registered manually.
|
||||
|
||||
如果我们忘了列出自定义管道,Angular会报告一个错误。
|
||||
我们不用在以前的例子中列出`DatePipe`,是因为所有的Angular内建管道都被预先注册过了。
|
||||
而自定义管道就必须被手动注册。
|
||||
|
||||
p.
|
||||
If we try the #[+liveExampleLink()],
|
||||
we can probe its behavior by changing the value and the optional exponent in the template.
|
||||
|
||||
p.
|
||||
试试这个#[+liveExampleLink('在线例子')],然后在模板中修改能量值和可选的放大指数,就能探测它行为方式。
|
||||
|
||||
: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)
|
||||
## 能力倍增计算器(加分项)
|
||||
|
||||
|
@ -346,12 +337,10 @@ a#change-detection
|
|||
p.
|
||||
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.
|
||||
|
||||
p.
|
||||
如果我们现在就运行这个例子,我们会看到一些古怪的行为(在#[+liveExampleLink('在线例子')]中试试)。
|
||||
我们添加的每个英雄都会飞,但他们一个都没有显示出来。
|
||||
|
||||
: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.
|
||||
It's just using a different change detection algorithm — one that ignores changes to the list or any of its items.
|
||||
|
||||
|
@ -527,11 +516,10 @@ block pure-change
|
|||
我们可以从`FlyingHeroesComponent`派生出一个`FlyingHeroesImpureComponent`。
|
||||
|
||||
+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.
|
||||
We can confirm in the #[+liveExampleLink()] that the #[i flying heroes]
|
||||
display updates as we enter new heroes even when we mutate the
|
||||
#[code heroes] #{_array}.
|
||||
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 `heroes` #{_array}.
|
||||
|
||||
p.
|
||||
唯一的重大改动就是管道。
|
||||
|
|
|
@ -1458,7 +1458,7 @@ h4#snapshot <i>快照</i>:不需要可观察(no-observable)时的替代方
|
|||
假如我们很确定`HeroDetailComponent`组件*永远、永远*不会被复用,每次导航到英雄详情时都会重新创建该组件。
|
||||
|
||||
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:
|
||||
|
||||
路由器提供了一个备选方案:*快照(snapshot)*,它会给我们路由参数的初始值。这样我们就不用订阅,也就不用不得不在`ngDestroy`中反订阅了。
|
||||
|
|
|
@ -40,11 +40,9 @@ block includes
|
|||
|
||||
* [Auditing Angular Applications](#code-review)
|
||||
|
||||
* [审计Angular应用程序](#code-review)
|
||||
|
||||
p Try the #[+liveExampleLink2()] of the code shown in this chapter.
|
||||
|
||||
p 运行#[+liveExampleLink2('在线例子')]
|
||||
Try the <live-example></live-example> of the code shown in this chapter.
|
||||
|
||||
运行<live-example></live-example>来试用本章中的代码。
|
||||
|
||||
.l-main-section
|
||||
h2#report-issues Reporting Vulnerabilities
|
||||
|
|
|
@ -32,90 +32,96 @@ block includes
|
|||
|
||||
!{_Angular_http_libraryCn}简化了**XHR**和**JSONP** API的编程,这就是本章所要讲的。
|
||||
|
||||
ul
|
||||
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") 把数据发送到服务器]
|
||||
- [HTTP client sample overview](#http-client)
|
||||
|
||||
+ifDocsFor('ts')
|
||||
li #[a(href="#promises") Promises instead of observables]
|
||||
- [HTTP客户端范例概览](#http-client)
|
||||
|
||||
- [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)]
|
||||
|
||||
li #[a(href="#cors") Cross-origin requests: Wikipedia 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('在线版')]中展示了这些主题,你可以在浏览器中运行它们。
|
||||
We illustrate these topics with code that you can <live-example>run live</live-example>.
|
||||
|
||||
我们在<live-example>在线例子</live-example>中展示了这些主题,你可以在浏览器中运行它们。
|
||||
|
||||
.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
|
||||
These demos are orchestrated by the root `AppComponent`
|
||||
|
||||
这些演示由根组件`AppComponent`统一演示。
|
||||
+makeExample('server-communication/ts/app/app.component.ts', null, 'app/app.component.ts')
|
||||
|
||||
block rxjs-import
|
||||
+ifDocsFor('ts')
|
||||
:marked
|
||||
There is nothing remarkable here _except_ for the import of RxJS operators.
|
||||
|
||||
|
@ -128,18 +134,18 @@ block rxjs-import
|
|||
:marked
|
||||
First, we have to configure our application to use server communication facilities.
|
||||
|
||||
首先,我们必须配置应用程序,才能使用服务器通讯设施。
|
||||
.l-main-section
|
||||
h1#http-providers Providing HTTP Services
|
||||
|
||||
h1#http-providers 提供HTTP服务
|
||||
|
||||
.l-main-section#http-providers
|
||||
:marked
|
||||
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}.
|
||||
# Providing HTTP Services
|
||||
|
||||
我们通过!{_Angular_Http}客户端,使用熟悉的HTTP请求/回应协议与服务器通讯。`#{_Http}`客户端是!{_Angular_http_libraryCn}所提供的服务大家庭中的一员。
|
||||
block system-config-of-http
|
||||
# 提供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
|
||||
:marked
|
||||
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)一章。
|
||||
|
||||
p In this demo, we register providers in the #[code bootstrap] method of #[code #[+adjExPath('app/main.ts')]].
|
||||
p 在这个例子中,我们在#[code #[+adjExPath('app/main.ts')]]文件的#[code bootstrap]方法中注册供应商。
|
||||
:marked
|
||||
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='.')
|
||||
|
||||
block http-providers
|
||||
|
@ -199,10 +209,12 @@ block http-providers
|
|||
这种“偷梁换柱”的把戏是应用程序的根组件*不应该*察觉的。
|
||||
正因为这*一个*理由,我们把它藏在`main.ts`里,在层次上高于`AppComponent`。
|
||||
|
||||
.l-main-section
|
||||
h1#http-client The Tour of Heroes #[i HTTP] Client Demo
|
||||
h1#http-client 《英雄指南》#[i HTTP]客户端的演示
|
||||
.l-main-section#http-client
|
||||
: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.
|
||||
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)`.
|
||||
|
@ -308,11 +320,13 @@ block getheroes-and-addhero
|
|||
|
||||
关于组件的浅显讲解已经结束了,我们可以到`HeroService`的内部实现中看看。
|
||||
|
||||
.l-main-section
|
||||
a#HeroService
|
||||
h2#fetch-data Fetch data with the #[b HeroService]
|
||||
h2#fetch-data 通过#[b HeroService]获取数据
|
||||
.l-main-section#fetch-data
|
||||
:marked
|
||||
## Fetch data with the **HeroService**
|
||||
|
||||
## 通过**HeroService**获取数据
|
||||
|
||||
In many of our previous samples we faked the interaction with the server by
|
||||
returning mock heroes in a service like this one:
|
||||
|
||||
|
@ -332,9 +346,10 @@ h2#fetch-data 通过#[b HeroService]获取数据
|
|||
注意,这个“!{_Angular_Http}客户端”服务[被注入](dependency-injection.html)到了`HeroService`的构造函数中。
|
||||
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'ctor')
|
||||
: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=".")
|
||||
:marked
|
||||
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就行了:
|
||||
+makeExample('server-communication/ts/app/toh/hero.service.ts', 'endpoint-json')(format=".")
|
||||
|
||||
block rxjs
|
||||
+ifDocsFor('ts')
|
||||
:marked
|
||||
<a id="rxjs"></a>
|
||||
The return value may surprise us.
|
||||
|
@ -455,9 +470,9 @@ a#extract-data
|
|||
|
||||
## 处理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=".")
|
||||
:marked
|
||||
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
|
||||
: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`
|
||||
property. We have to unwrap it to get the heroes.
|
||||
This is conventional web api behavior, driven by
|
||||
|
@ -532,7 +547,7 @@ block parse-json
|
|||
|
||||
header HTTP的GET方法被推迟执行了
|
||||
: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)
|
||||
which means the request won't go out until something *subscribes* to the observable.
|
||||
That *something* is the [HeroListComponent](#subscribe).
|
||||
|
@ -587,7 +602,7 @@ h4 #[b HeroListComponent] error handling
|
|||
h4 #[b HeroListComponent] 错误处理
|
||||
block hlc-error-handling
|
||||
: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.
|
||||
It sets an `errorMessage` variable which we've bound conditionally in the `HeroListComponent` template.
|
||||
|
||||
|
@ -699,9 +714,9 @@ code-example(format="." language="javascript").
|
|||
### JSON结果
|
||||
|
||||
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
|
||||
:marked
|
||||
|
@ -712,7 +727,7 @@ block hero-list-comp-add-hero
|
|||
当有数据到来时,它就会把这个新的英雄对象追加(push)到`heroes`数组中,以展现给用户。
|
||||
+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 倒退为承诺(Promise)
|
||||
|
@ -849,7 +864,7 @@ figure.image-display
|
|||
block wikipedia-jsonp+
|
||||
:marked
|
||||
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.
|
||||
|
||||
Wikipedia提供了一个现代的`CORS` API和一个传统的`JSONP`搜索API。在这个例子中,我们使用后者。
|
||||
|
@ -939,7 +954,7 @@ block wikipedia-jsonp+
|
|||
该组件有一个`<input>`元素,它是用来从用户获取搜索关键词的*搜索框*。
|
||||
在每次`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`,
|
||||
we forward the observable result to the template (via `items`) where the [async pipe](pipes.html#async-pipe)
|
||||
in the `ngFor` handles the subscription.
|
||||
|
@ -1158,9 +1173,9 @@ a#in-mem-web-api
|
|||
并且通过SystemJS(参见`systemjs.config.js`)把它注册进模块加载器。
|
||||
|
||||
: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
|
||||
are #{_array}s of objects in those collections.
|
||||
are !{_array}s of objects in those collections.
|
||||
|
||||
内存Web API从一个带有`createDb()`方法的自定义类中获取数据,并且返回一个map,它的主键(key)是一组名字,而值(value)是一组与之对应的对象数组。
|
||||
|
||||
|
@ -1190,11 +1205,15 @@ block redirect-to-web-api
|
|||
|
||||
要想启用我们的服务模拟器,我们通过Angular标准的“供应商注册”技术,把默认的`XHRBackend`服务替换为了这个内存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')]]版本,用于演示这些步骤。
|
||||
+makeExample('server-communication/ts/app/main.ts', 'final', 'app/main.ts (final)')(format=".")
|
||||
|
||||
p See the full source code in the #[+liveExampleLink2()].
|
||||
p 要想查看完整的源代码,参见#[+liveExampleLink2('浏览器中运行在线版')]。
|
||||
:marked
|
||||
See the full source code in the <live-example></live-example>.
|
||||
|
||||
要想查看完整的源代码,请参见<live-example></live-example>。
|
||||
|
|
|
@ -26,8 +26,9 @@ block includes
|
|||
- [write our own structural directive](#unless)
|
||||
- [写我们自己的结构型指令](#unless)
|
||||
|
||||
p Try the #[+liveExampleLink2()].
|
||||
p 试试#[+liveExampleLink2('在线例子')].
|
||||
Try the <live-example></live-example>.
|
||||
|
||||
试试<live-example></live-example>。
|
||||
|
||||
<a id="definition"></a>
|
||||
.l-main-section
|
||||
|
|
|
@ -63,8 +63,7 @@ block includes
|
|||
* [safe navigation operator (?.)](#safe-navigation-operator)
|
||||
* [“安全导航操作符”(?.)](#safe-navigation-operator)
|
||||
|
||||
p.
|
||||
The #[+liveExampleLink2()]
|
||||
The <live-example></live-example>
|
||||
demonstrates all of the syntax and code snippets described in this chapter.
|
||||
p.
|
||||
这个#[+liveExampleLink2('在线例子')]演示了本章中描述的所有语法和代码片段。
|
||||
|
|
|
@ -27,25 +27,30 @@ block includes
|
|||
虽然我们正在用#{_Lang},但你也可以用#{_docsFor == 'ts' ? 'Dart' : 'TypeScript'}和JavaScript来写Angular 2应用。
|
||||
只要从Banner区的下拉框选择想用的那种语言就可以了。
|
||||
|
||||
h1 Try it!
|
||||
h1 试试!
|
||||
p
|
||||
| Try the #[+liveExampleLink2()] which loads the sample app
|
||||
+ifDocsFor('ts')
|
||||
| in #[a(href="http://plnkr.co/" title="Plunker" target="_blank") plunker]
|
||||
| and displays the simple message:
|
||||
p
|
||||
| 试试#[+liveExampleLink2('在线范例', 'quickstart')],它将把此范例加载
|
||||
+ifDocsFor('ts')
|
||||
| 到 #[a(href="http://plnkr.co/" title="Plunker" target="_blank") plunker]中
|
||||
| 并显示一条简单的消息:
|
||||
:marked
|
||||
# Try it!
|
||||
|
||||
# 试试
|
||||
|
||||
Try the <live-example></live-example> which loads the sample app
|
||||
<span if-docs="ts">
|
||||
in <a href="http://plnkr.co/" title="Plunker" target="_blank">plunker</a>
|
||||
</span>
|
||||
and displays the simple message:
|
||||
|
||||
试试这个<live-example></live-example>,它将把此范例加载到
|
||||
<span if-docs="ts">
|
||||
<a href="http://plnkr.co/" title="Plunker" target="_blank">plunker</a>中
|
||||
</span>
|
||||
,并显示一条简单的消息:
|
||||
|
||||
figure.image-display
|
||||
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="“快速起步”应用的输出")
|
||||
|
||||
h1 Build this app!
|
||||
h1 构建此应用!
|
||||
:marked
|
||||
# Build this app!
|
||||
# 构建此应用!
|
||||
|
||||
- [Prerequisite](#prereq): Install #{_prereq}
|
||||
- [环境准备](#prereq): 安装#{_prereq}
|
||||
- [Step 1](#create-and-configure): Create the app’s project folder and
|
||||
|
@ -53,8 +58,8 @@ h1 构建此应用!
|
|||
- [步骤1](#create-and-configure):创建本应用的项目文件夹,并且定义包的依赖以及特别的项目设置。
|
||||
- [Step 2](#root-component): Create the app’s Angular root component
|
||||
- [步骤2](#root-component): 创建本应用的Angular根组件
|
||||
- [Step 3](#main): Add `main.#{_docsFor}`, identifying the root component to Angular
|
||||
- [步骤3](#main):添加`main.#{_docsFor}`,用来告诉Angular哪个是根组件。
|
||||
- [Step 3](#main): Add <span ngio-ex>main.ts</span>, identifying the root component to Angular
|
||||
- [步骤3](#main):添加<span ngio-ex>main.ts</span>,用来告诉Angular哪个是根组件。
|
||||
- [Step 4](#index): Add `index.html`, the web page that hosts the application
|
||||
- [步骤4](#index):添加`index.html`,本应用的宿主页面。
|
||||
- [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/)**,请安装它们。
|
||||
.l-sub-section
|
||||
: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.
|
||||
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)更加容易。
|
||||
要达成这些目标,我们需要从其它库中引入一个不同类型的`bootstrap`函数。
|
||||
|
||||
### Why create separate *main.#{_docsFor}* and app component files?
|
||||
### 为什么创建一个分离的*main.#{_docsFor}*文件和应用组件文件?
|
||||
### Why create separate *<span ngio-ex>main.ts</span>* and app component files?
|
||||
### 为什么创建一个分离的*<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.
|
||||
We could have merged these two files into one
|
||||
and spared ourselves some complexity.
|
||||
|
||||
无论是`main.#{_docsFor}`还是组件的文件都非常小。
|
||||
无论是<span ngio-ex>main.ts</span>还是组件的文件都非常小。
|
||||
它只是一个“快速起步”而已。
|
||||
我们本可以把这两个文件装进`app.component`文件来减少一点复杂度。
|
||||
|
||||
|
@ -728,7 +733,7 @@ h2#index 步骤4:添加#[code index.html]
|
|||
|
||||
a(id="my-app")
|
||||
: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`,
|
||||
and renders our application's view between those tags.
|
||||
|
||||
|
|
|
@ -43,13 +43,13 @@ include ../_util-fns
|
|||
|
||||
我们将学习足够的Angular核心技术,来作为起步,并建立信心 —— 证明Angular确实能做到我们想让它做的。
|
||||
虽然我们将覆盖大部分“简介级”知识,但还是会放上大量链接,指向更深入的章节。
|
||||
|
||||
Run the <live-example name="toh-6"></live-example>.
|
||||
|
||||
运行<live-example name="toh-6"></live-example>。
|
||||
|
||||
// #enddocregion intro
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-6')].
|
||||
|
||||
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-6')]。
|
||||
|
||||
// #docregion main
|
||||
.l-main-section
|
||||
:marked
|
||||
|
|
|
@ -9,11 +9,10 @@ include ../_util-fns
|
|||
|
||||
每一个故事,都有一个起点。而我们的故事则开始于[“快速起步”](../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
|
||||
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`的其它绑定。
|
||||
|
||||
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:
|
||||
|
||||
完整的`app.component.ts`是这样的:
|
||||
|
|
|
@ -9,13 +9,10 @@ include ../_util-fns
|
|||
We’ll expand our Tour of Heroes app to display a list of heroes,
|
||||
allow the user to select a hero, and display the hero’s 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
|
||||
Let’s take stock of what we’ll need to display a list of heroes.
|
||||
First, we need a list of heroes. We want to display those heroes in the view’s template,
|
||||
so we’ll need a way to do that.
|
||||
|
@ -524,11 +521,10 @@ code-example(language="bash").
|
|||
|
||||
* 我们学会了如何在组件模板中使用内建的`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
|
||||
|
||||
### 前方的路
|
||||
|
|
|
@ -4,10 +4,9 @@ include ../_util-fns
|
|||
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.
|
||||
|
||||
我们的应用继续成长。
|
||||
这次的例子将依次展示:复用组件、给组件传入数据以及创建更容易复用的软件资产。我们先把英雄列表从英雄详情中分离出来,并且让详情组件可复用。
|
||||
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')]。
|
||||
|
||||
|
@ -418,7 +417,7 @@ code-example(format=".").
|
|||
|
||||
* 我们学会了在`directives`中定义应用所需的指令。
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-3')] for this part.
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-3')]。
|
||||
|
||||
|
|
|
@ -26,11 +26,9 @@ include ../_util-fns
|
|||
Because data services are invariably asynchronous,
|
||||
we'll finish the chapter with a **!{_Promise}**-based version of the data service.
|
||||
|
||||
因为数据服务通常都是异步的,所以在本章的最后,我们会把它重构为基于承诺(Promise,一种异步编程模式)的版本。
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-4')]。
|
||||
运行这部分的<live-example></live-example>。
|
||||
|
||||
.l-main-section
|
||||
: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
|
||||
|
||||
### 前方的路
|
||||
|
|
|
@ -41,11 +41,10 @@ figure.image-display
|
|||
The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail
|
||||
than we will in this tutorial.
|
||||
|
||||
[路由与导航](../guide/router.html)一章覆盖了比该教程中更详细的路由知识。
|
||||
|
||||
p Run the #[+liveExampleLink2('', 'toh-5')] for this part.
|
||||
|
||||
p 运行这部分的#[+liveExampleLink2('在线例子', 'toh-5')]。
|
||||
:marked
|
||||
Run the <live-example></live-example> for this part.
|
||||
|
||||
运行这部分的<live-example></live-example>。
|
||||
|
||||
.l-sub-section
|
||||
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
|
||||
:marked
|
||||
## 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:
|
||||
|
||||
在<live-example></live-example>中回顾本章的范例代码。
|
||||
验证我们是否已经得到了如下结构:
|
||||
|
||||
p.
|
||||
在#[+liveExampleLink2('在线例子', 'toh-5')]中回顾这部分代码。
|
||||
验证我们是否已经得到了下列结构:
|
||||
|
||||
:marked
|
||||
.filetree
|
||||
.file angular2-tour-of-heroes
|
||||
.children
|
||||
|
|
|
@ -24,7 +24,7 @@ block includes
|
|||
|
||||
在这一章中,我们要让应用程序学会通过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')]。
|
||||
|
||||
|
@ -91,7 +91,7 @@ block http-providers
|
|||
|
||||
:marked
|
||||
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`.
|
||||
|
||||
我们要能从本应用的任何地方访问这些服务,所以,就要在`main.ts`中的`bootstrap`方法中注册它们。
|
||||
|
@ -604,14 +604,13 @@ block review
|
|||
:marked
|
||||
## Application structure and code
|
||||
|
||||
### 回顾应用结构
|
||||
## 应用的结构与代码
|
||||
|
||||
p.
|
||||
Review the sample source code in the #[+liveExampleLink2('', 'toh-6')] for this chapter.
|
||||
Review the sample source code in the <live-example></live-example> for this chapter.
|
||||
Verify that we have the following structure:
|
||||
|
||||
p.
|
||||
在#[+liveExampleLink2('', 'toh-6')]中回顾本章的范例代码,验证是否得到了如下结构:
|
||||
|
||||
在<live-example></live-example>中回顾本章的范例代码。
|
||||
验证我们是否得到了如下结构:
|
||||
|
||||
block filetree
|
||||
.filetree
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -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) { };
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -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) { };
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -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;
|
||||
} ());
|
|
@ -76,7 +76,7 @@ div(layout="row" layout-xs="column" class="row-margin ng-cloak")
|
|||
div(flex="80" flex-xs="100")
|
||||
{%- for decorator in doc.decorators %}
|
||||
pre.prettyprint.no-bg
|
||||
code(class="api-doc-code")
|
||||
code(class="api-doc-code").
|
||||
@{$ decorator.name $}{$ paramList(decorator.arguments) | indent(10, false) $}
|
||||
:marked
|
||||
{%- if not decorator.notYetDocumented %}
|
||||
|
|
Loading…
Reference in New Issue