Merge remote-tracking branch 'cn/master'

This commit is contained in:
Zhicheng Wang 2016-07-01 08:25:35 +08:00
commit dfc20a6adc
2 changed files with 46 additions and 34 deletions

View File

@ -2092,7 +2092,7 @@ h3#can-activate-guard <i>CanActivate</i>: 要求认证
Currently every route within our *Crisis Center* is open to everyone.
The new *admin* feature should be accessible only to authenticated users.
现在“危机中心”的每个路由都是对每个人开放的。这些新的*管理特性*应该只能被已登录用户访问
现在“危机中心”的每个路由都是对所有人开放的。这些新的*管理特性*应该只能被已登录用户访问。
We could hide the link until the user logs in. But that's tricky and difficult to maintain.
@ -2105,7 +2105,7 @@ h3#can-activate-guard <i>CanActivate</i>: 要求认证
This is a general purpose guard &mdash; we can imagine other features that require authenticated users &mdash;
so we create an `auth.guard.ts` in the application root folder.
这是一种具有通用性的守护目标(想象下会有其它特性需要登录用户才能访问),所以我们在应用的根目录下创建一个`auth.guard.ts`文件。
这是一种具有通用性的守护目标(通常会有其它特性需要登录用户才能访问),所以我们在应用的根目录下创建一个`auth.guard.ts`文件。
At the moment we're interested in seeing how guards work so our first version does nothing useful.
It simply logs to console and `returns` true immediately, allowing navigation to proceed:
@ -2118,7 +2118,7 @@ h3#can-activate-guard <i>CanActivate</i>: 要求认证
Next we open `crisis-center.routes.ts `, import the `AuthGuard` class, and
update the admin route with a `CanActivate` guard property that references it:
接下来,我们打开`crisis-center.routes.ts`,导入`AuthGuard`类,,修改管理路由并通过`canActivate`属性来引用`AuthGuard`
接下来,打开`crisis-center.routes.ts`,导入`AuthGuard`类,修改管理路由并通过`CanActivate`属性来引用`AuthGuard`
+makeExample('router/ts/app/crisis-center/crisis-center.routes.ts', 'admin-route', 'crisis-center.routes.ts (guarded admin route)')(format=".")
@ -2148,9 +2148,9 @@ h3#can-activate-guard <i>CanActivate</i>: 要求认证
It has an `isLoggedIn` flag to tell us whether the user is authenticated.
Its `login` method simulates an API call to an external service by returning an observable that resolves successfully after a short pause.
虽然它不会真的进行登录,但它却足够我们进行讨论了。
它有一个`isLoggedIn`标志,用来告诉我们是否用户已经登录过了。
它的`login`方法会仿真一个对外部服务的API调用返回一个可观察对象observable。在短暂的停顿之后这个可观察对象就会解析成功。
虽然它不会真的进行登录,但足够我们进行这个讨论了。
它有一个`isLoggedIn`标志,用来标识是否用户已经登录过了。
它的`login`方法会仿真一个对外部服务的API调用返回一个可观察对象observable。在短暂的停顿之后这个可观察对象就会解析成功。
Let's revise our `AuthGuard` to call it.
@ -2214,25 +2214,25 @@ h3#can-deactivate-guard <i>CanDeactivate</i>:处理未保存的更改
cancels and reverts all changes.
在现实世界中,我们得先把用户的改动积累起来。
我们可能不得不进行跨字段的校验,可能要找服务器进行校验,可能得把这些改动保存成一种待定状态,直到用户或者把这些改动*作为一组*进行确认或撤销所有改动。
我们可能不得不进行跨字段的校验,可能要找服务器进行校验,可能得把这些改动保存成一种待定状态,直到用户或者把这些改动*作为一组*进行确认或撤销所有改动。
What do we do about unapproved, unsaved changes when the user navigates away?
We can't just leave and risk losing the user's changes; that would be a terrible experience.
当用户要导航到外面时,我们该怎么处理这些既没有审核通过又没有保存过的改动呢?
当用户要导航到外面时,该怎么处理这些既没有审核通过又没有保存过的改动呢?
我们不能马上离开,不在乎丢失这些改动的风险,那显然是一种糟糕的用户体验。
We'd like to pause and let the user decide what to do.
If the user cancels, we'll stay put and allow more changes.
If the user approves, the app can save.
我们应该暂停,并让用户决定该怎么做。如果用户选择了取消,我们就留下来,并更多改动。如果用户选择了确认,那就进行保存。
我们应该暂停,并让用户决定该怎么做。如果用户选择了取消,我们就留下来,并允许更多改动。如果用户选择了确认,那就进行保存。
We still might delay navigation until the save succeeds.
If we let the user move to the next screen immediately and
the save failed (perhaps the data are ruled invalid), we would have lost the context of the error.
在保存成功之前,我们还可以继续推迟导航。如果我们让用户立即移到下一个界面,而保存却失败了(可能因为数据不符合有效性规则),我们就会丢该错误的上下文环境。
在保存成功之前,我们还可以继续推迟导航。如果我们让用户立即移到下一个界面,而保存却失败了(可能因为数据不符合有效性规则),我们就会丢该错误的上下文环境。
We can't block while waiting for the server &mdash; that's not possible in a browser.
We need to stop the navigation while we wait, asynchronously, for the server
@ -2276,14 +2276,14 @@ h3#can-deactivate-guard <i>CanDeactivate</i>:处理未保存的更改
Should the app save or cancel automatically?
如果用户尝试不保存或撤销就导航到外面该怎么办?
用户可以按浏览器的后退按钮,或点击英雄的链接。
用户可以按浏览器的后退按钮,或点击英雄的链接。
这些操作都会触发导航。本应用应该自动保存或取消吗?
We'll do neither. Instead we'll ask the user to make that choice explicitly
in a confirmation dialog box that *waits asynchronously for the user's
answer*.
都不行。我们应该弹出一个确认对话框来要求用户明确做出选择,该对话框会*用异步的方式等用户做出选择*。
我们两个都不采取。我们应该弹出一个确认对话框来要求用户明确做出选择,该对话框会*用异步的方式等用户做出选择*。
.l-sub-section
@ -2433,12 +2433,12 @@ figure.image-display
Multiple values are common &mdash; `after='12/31/2015' & before='1/1/2017'` &mdash; in no particular order &mdash;
`before='1/1/2017' & after='12/31/2015'` &mdash; in a variety of formats &mdash; `during='currentYear'` .
可选的信息使用其它形式表示。搜索标准通常是结构松散的,例如`name='wind*'`;多个值的情况是普遍存在的(如`after='12/31/2015' & before='1/1/2017'`);也没有特定的顺序(如`before='1/1/2017' & after='12/31/2015'`;有多种多样的格式(如`during='currentYear'`)。
可选的信息使用其它形式表示。搜索标准通常是结构松散的,例如`name='wind*'`;多个值的情况是普遍存在的(如`after='12/31/2015' & before='1/1/2017'`);也没有特定的顺序(如`before='1/1/2017' & after='12/31/2015'`有多种多样的格式(如`during='currentYear'`)。
These kinds of parameters don't fit easily in a URL *path*. Even if we could define a suitable URL token scheme,
doing so greatly complicates the pattern matching required to translate an incoming URL to a named route.
这些类型的参数不适合用在URL*路径*中。即使我们能定义一个合适的URL令牌方案它也会让从输入URL翻译成命名路由的模式匹配算法变得非常复杂。
这些类型的参数不适合用在URL*路径*中。即使我们能定义一个合适的URL令牌方案它也会让从输入URL翻译成命名路由所需要的模式匹配算法变得非常复杂。
The **URL query string** is the ideal vehicle for conveying arbitrarily complex information during navigation.
The query string isn't involved in pattern matching and affords enormous flexiblity of expression.
@ -2471,7 +2471,7 @@ figure.image-display
* the value is necessary to distinguish one route path from another.
* 这个值对于把此路由的路径与另一个区分开是有必要的。
* 这个值对于把一个路由路径与另一个区分开是有必要的。
*prefer a query parameter when*
@ -2587,7 +2587,7 @@ code-example(format="." language="bash").
row because it demonstrates the final state of the application which includes the steps we're *about* to cover.
At the moment we're describing the state of affairs *prior* to those steps.
[在线例子](/resources/live-examples/router/ts/plnkr.html)*会*高亮显示选中的行,因为它显示的是应用中的最终状态,它包括一些我们*即将*涉及的步骤。接下来,我们就来讲讲这些中间步骤。
[在线例子](/resources/live-examples/router/ts/plnkr.html)*会*高亮显示选中的行,因为它显示的是应用中的最终状态,它包括一些我们*即将*涉及的步骤。接下来,我们就来讲讲这些中间步骤。
:marked
The `HeroListComponent` isn't expecting any parameters at all and wouldn't know what to do with them.
@ -2731,7 +2731,7 @@ code-example(format="." language="bash").
as long as the URL can be emailed and pasted into a browser address bar
as this one can.
对我们来说,这种语法看起来可能有点奇怪但用户不大可能注意到或关心这一点因为标准的URL能被邮件出去或传到浏览器地址栏这种也可以。
对我们来说,这种语法看起来可能有点奇怪。但是只要这种URL能被邮件出去或传到浏览器地址栏用户不大可能注意到或关心这一点这种方法恰巧可以。
<a id="final-app"></a>
@ -2746,7 +2746,7 @@ code-example(format="." language="bash").
Please visit the [live example](/resources/live-examples/router/ts/plnkr.html) and
where you can download the final source code.
本章中涉及到了很多背景知识,而且本应用程序也太大了,所以没法打印在这里。请访问[在线例子](/resources/live-examples/router/ts/plnkr.html),在那里你可以下载最终的源码。
本章中涉及到了很多背景知识,而且本应用程序也太大了,所以没法在这里显示。请访问[在线例子](/resources/live-examples/router/ts/plnkr.html),在那里你可以下载最终的源码。
.l-main-section
@ -2795,7 +2795,7 @@ code-example(format="." language="bash").
These two examples cover our needs for an app with one level routing.
The moment we add a child router, such as the *Crisis Center*, we create new link array possibilities.
这两个例子覆盖了我们在单级路由的应用中所需的一切。该添加一个子路由了,就像在*危机中心*中,我们创建新链接数组那样
这两个例子覆盖了我们在单级路由的应用中所需的一切。在添加一个像*危机中心*一样的子路由时,我们创建新链接数组组合
Recall that we specified a default child route for *Crisis Center* so this simple `RouterLink` is fine.
@ -2888,13 +2888,13 @@ code-example(format="." language="bash").
We did so, for example, in the [HeroDetailComponent](#hero-detail-ctor).
We might have put the `ngOnInit` logic inside the constructor instead. We didn't for a reason. The reason is *testability*.
我们在很多组件类中实现了`ngOnInit`方法。比如在[HeroDetailComponent](#hero-detail-ctor)中就这么用过。我们也可以把`ngOnInit`中的逻辑放在构造函数中,但我们为了一个理由而没那么做,这个理由就是*可测试性*。
我们在很多组件类中实现了`ngOnInit`方法。比如在[HeroDetailComponent](#hero-detail-ctor)中就这么用过。也可以把`ngOnInit`中的逻辑放在构造函数中,但为了一个理由而没那么做,这个理由就是*可测试性*。
A constructor that has major side-effects can be difficult to test because it starts doing things as soon as
we create a test instance. In this case, it might have made a request to a remote server, something it shouldn't
do under test. It may even be impossible to reach the server in the test environment.
有显著副作用的构造函数很难测试,因为它在创建测试实例时就开始做事了。这种情况下,它可能已经向远程服务器发起了请求,但有些事情在测试时没法做。甚至在测试环境下访问服务器都是不可能的
有显著副作用的构造函数很难测试,因为它在创建测试实例时就开始做事了。这种情况下,它可能已经向远程服务器发起了请求,但有些事情在测试时没法做。可能在测试环境下无法访问服务器
The better practice is to limit what the constructor can do. Mostly it should stash parameters in
local variables and perform simple instance configuration.
@ -3014,7 +3014,7 @@ code-example(format=".", language="bash").
It produces URLs that are easier for users to understand.
And it preserves the option to do **server-side rendering** later.
几乎所有的Angular 2项目都会使用默认的HTML 5风格。它生成的URL更易于被用户理解它也为将来做**服务端渲染**预留了选项
几乎所有的Angular 2项目都会使用默认的HTML 5风格。它生成的URL更易于被用户理解它也为将来做**服务端渲染**预留了空间
Rendering critical pages on the server is a technique that can greatly improve
perceived responsiveness when the app first loads.
@ -3057,7 +3057,7 @@ code-example(format=".", language="bash").
Bad things could happen when someone pastes an application link into the
browser's address bar or clicks such a link in an email link.
如果没有此标签当通过“深链接”进入该应用时浏览器就不能加载资源图片、CSS、脚本这种事会发生在有人把应用的链接粘贴进浏览器的地址栏或从邮件中点击应用的链接时。
如果没有此标签当通过“深链接”进入该应用时浏览器就不能加载资源图片、CSS、脚本如果有人把应用的链接粘贴进浏览器的地址栏或从邮件中点击应用的链接时,这种问题就发生
Some developers may not be able to add the `<base>` element, perhaps because they don't have
access to `<head>` or the `index.html`.

View File

@ -17,8 +17,8 @@ block includes
Now they want to get the hero data from a server, let users add, edit, and delete heroes,
and save these changes back to the server.
客户很欣赏我们的进展
现在,他们想要从服务器获取英雄数据,然后让用户添加、编和删除英雄,并且把这些修改结果保存回服务器。
客户对我们的进展很满意
现在,他们想要从服务器获取英雄数据,然后让用户添加、编和删除英雄,并且把这些修改结果保存回服务器。
In this chapter we teach our application to make the corresponding HTTP calls to a remote server's web API.
@ -70,8 +70,7 @@ block http-library
shipped in a separate script file as part of the Angular npm package.
`Http`***并不是***Angular的核心模块。
它是Angular用来进行Web访问的一种可选方式并通过Angular包中一个名叫`@angular/http`的独立附属模块发布了出来。
它是Angular用来进行Web访问的一种可选方式并通过Angular包中一个名叫`@angular/http`的独立附属模块发布了出来。
Fortunately we're ready to import from `@angular/http` because `systemjs.config` configured *SystemJS* to load that library when we need it.
@ -95,7 +94,8 @@ block http-providers
So we register them in the `bootstrap` call of `main.!{_docsFor}` where we
launch the application and its root `AppComponent`.
我们要能从本应用的任何地方访问这些服务,所以,我们就要在`main.ts`中的`bootstrap`方法中注册它们。这里同时也是我们启动应用及其根组件`AppComponent`的地方。
我们要能从本应用的任何地方访问这些服务,所以,就要在`main.ts`中的`bootstrap`方法中注册它们。
这里同时也是我们启动应用及其根组件`AppComponent`的地方。
+makeExcerpt('app/main.ts','v1')
@ -191,7 +191,7 @@ block dont-be-distracted-by-backend-subst
That day has arrived! Let's convert `getHeroes()` to use HTTP:
一天到来了!我们把`getHeroes()`换成用HTTP。
一天到来了!我们把`getHeroes()`换成用HTTP。
+makeExcerpt('app/hero.service.ts (new constructor and revised getHeroes)', 'getHeroes')
@ -202,6 +202,8 @@ block dont-be-distracted-by-backend-subst
We're still returning a !{_Promise} but we're creating it differently.
我们仍然返回一个承诺,但是用不同的方法来创建它。
block get-heroes-details
:marked
The Angular `http.get` returns an RxJS `Observable`.
@ -332,7 +334,7 @@ block get-heroes-details
We'll complete `HeroService` by creating `post`, `put` and `delete` methods to meet our new requirements.
我们将为`HeroService`添加`post`、`put`和`delete`的http调用来彻底满足我们的需求。
我们将为`HeroService`添加`post`、`put`和`delete`的http调用来满足我们的需求。
:marked
### Post
@ -418,6 +420,8 @@ block hero-detail-comp-extra-imports-and-vars
block hero-detail-comp-updates
:marked
### Add/Edit in the *HeroDetailComponent*
### 在*HeroDetailComponent*中添加和编辑英雄
We already have `HeroDetailComponent` for viewing details about a specific hero.
Add and Edit are natural extensions of the detail view, so we are able to reuse `HeroDetailComponent` with a few tweaks.
@ -440,6 +444,8 @@ block hero-detail-comp-updates
:marked
Add a save method to `HeroDetailComponent` and call the corresponding save method in `HeroesService`.
在`HeroDetailComponent`中添加一个`save`方法,用来从`HeroService`调用对应的`save`方法
+makeExcerpt('app/hero-detail.component.ts', 'save')
block hero-detail-comp-save-and-goback
@ -464,7 +470,7 @@ block hero-detail-comp-save-and-goback
The `emit` "handshake" between `HeroDetailComponent` and `HeroesComponent` is an example of component to component communication. This is a topic for another day, but we have detailed information in our <a href="/docs/ts/latest/cookbook/component-communication.html#!#child-to-parent">Component Interaction Cookbook</a>
`emit`在`HeroDetailComponent`和`HeroesComponent`之间的这种握手是组件间通讯的例子之一。
这不是今天的话题,我们在<a href="/docs/ts/latest/cookbook/component-communication.html#!#child-to-parent">组件间交互</a>一章中讲了一些详细信息。
这不是今天的话题,在<a href="/docs/ts/latest/cookbook/component-communication.html#!#child-to-parent">组件间交互</a>一章中有相关详细信息。
:marked
Here is `HeroDetailComponent` with its new save button and the corresponding HTML.
@ -526,13 +532,15 @@ block add-new-hero-via-detail-comp
Now let's fix-up the `HeroesComponent` to support the *add* and *delete* actions used in the template.
Let's start with *add*.
现在,让我们修复`HeroesComponent`,让它支持模板中的*添加*和*删除*动作。以*添加*动作开始。
block heroes-comp-directives
:marked
We're using the `HeroDetailComponent` to capture the new hero information.
We have to tell Angular about that by importing the `HeroDetailComponent` and referencing it in the component metadata `directives` array.
我们正在用`HeroDetailComponent`捕获新英雄的信息。
为了告诉Angular这一点,我们还得导入`HeroDetailComponent`并把它加入组件元数据的`directives`数组中。
使用`HeroDetailComponent`来捕获新英雄的信息。
为了告诉Angular这一点导入`HeroDetailComponent`并把它加入组件元数据的`directives`数组中。
+makeExcerpt('app/heroes.component.ts (HeroDetailComponent)', 'hero-detail-component')
@ -541,7 +549,7 @@ block heroes-comp-directives
These are the same lines that we removed in the previous [Routing](toh-pt5.html) chapter.
We didn't know at the time that we'd need the *HeroDetailComponent* again. So we tidied up.
同样的这些代码,我们曾在前面的[路由](toh-pt5.html)一章中除过。
同样的这些代码,我们曾在前面的[路由](toh-pt5.html)一章中除过。
我们不知道现在会再次需要*`HeroDetailComponent`*类,所以把它们清理掉了。
Now we *must* put these lines back. If we don't, Angular will ignore the `<my-hero-detail>`
@ -575,6 +583,10 @@ block heroes-comp-add
But the component is still responsible for updating the display.
So the *delete* method removes the deleted hero from the list.
当然,我们把删除英雄并让其持久有效的工作交给`HeroesService`。
但是组件仍然需要负责更新显示。
所以*delete*方法从英雄列表移除被删除的英雄。
block review
:marked
### Let's see it