Polish toh-pt6.jade (round 2)
This commit is contained in:
parent
2040b6ecd2
commit
4e49ba9cd0
@ -21,11 +21,11 @@ block includes
|
|||||||
|
|
||||||
In this chapter we teach our application to make the corresponding HTTP calls to a remote server's web API.
|
In this chapter we teach our application to make the corresponding HTTP calls to a remote server's web API.
|
||||||
|
|
||||||
在这一章中,我们要让应用程序学会通过HTTP调用来访问远程服务器上相应的Web API。
|
在这一章中,我们要让应用程序通过 HTTP 调用来访问远程服务器上相应的 Web API。
|
||||||
|
|
||||||
Run the <live-example></live-example> for this part.
|
Run the <live-example></live-example> for this part.
|
||||||
|
|
||||||
p 运行这部分的<live-example>在线例子</live-example>。
|
运行这部分的<live-example>在线例子</live-example>。
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
@ -47,7 +47,7 @@ block start-server-and-watch
|
|||||||
Open a terminal/console window and enter the following command to
|
Open a terminal/console window and enter the following command to
|
||||||
start the TypeScript compiler, start the server, and watch for changes:
|
start the TypeScript compiler, start the server, and watch for changes:
|
||||||
|
|
||||||
打开terminal/console窗口,输入下列命令来启动TypeScript编译器,它会启动开发服务器,并监视文件变更:
|
打开终端/控制台窗口,输入下列命令来启动 TypeScript 编译器,它会启动开发服务器,并监视文件变更:
|
||||||
|
|
||||||
code-example(language="bash").
|
code-example(language="bash").
|
||||||
npm start
|
npm start
|
||||||
@ -113,7 +113,6 @@ block http-providers
|
|||||||
registering in `main` for a special reason.</span>
|
registering in `main` for a special reason.</span>
|
||||||
|
|
||||||
我们建议在根模块`!{_AppModuleVsAppComp}`的`providers`数组中注册全应用级的服务。
|
我们建议在根模块`!{_AppModuleVsAppComp}`的`providers`数组中注册全应用级的服务。
|
||||||
<span if-docs="dart">Here we're registering in `main` for a special reason.</span>
|
|
||||||
|
|
||||||
Our application is in the early stages of development and far from ready for production.
|
Our application is in the early stages of development and far from ready for production.
|
||||||
We don't even have a web server that can handle requests for heroes.
|
We don't even have a web server that can handle requests for heroes.
|
||||||
@ -128,10 +127,7 @@ block http-providers
|
|||||||
shouldn't know about this. So we'll slip the in-memory web API into the
|
shouldn't know about this. So we'll slip the in-memory web API into the
|
||||||
configuration *above* the `AppComponent`.</span>
|
configuration *above* the `AppComponent`.</span>
|
||||||
|
|
||||||
我们要*耍点小花招*,让http客户端从一个Mock服务(*内存(in-memory)Web API*)中获取和保存数据。
|
我们要*耍点小花招*,让 HTTP 客户端从一个模拟服务(*内存 Web API*)中获取和保存数据。
|
||||||
<span if-docs="dart"> The application itself doesn't need to know and
|
|
||||||
shouldn't know about this. So we'll slip the in-memory web API into the
|
|
||||||
configuration *above* the `AppComponent`.</span>
|
|
||||||
|
|
||||||
Here is a version of <span ngio-ex>!{_appModuleTsVsMainTs}</span> that performs this trick:
|
Here is a version of <span ngio-ex>!{_appModuleTsVsMainTs}</span> that performs this trick:
|
||||||
|
|
||||||
@ -147,7 +143,9 @@ block backend
|
|||||||
with an _in-memory web API alternative service_.
|
with an _in-memory web API alternative service_.
|
||||||
|
|
||||||
导入`InMemoryWebApiModule`并将其加入到模块的`imports`数组。
|
导入`InMemoryWebApiModule`并将其加入到模块的`imports`数组。
|
||||||
`InMemoryWebApiModule`将`Http`客户端默认的后端服务(这是一个辅助服务,负责与远程服务器对话)替换成了*内存Web API*服务:
|
`InMemoryWebApiModule`将`Http`客户端默认的后端服务 —
|
||||||
|
这是一个辅助服务,负责与远程服务器对话 —
|
||||||
|
替换成了*内存 Web API*服务:
|
||||||
|
|
||||||
+makeExcerpt(_appModuleTsVsMainTs, 'in-mem-web-api', '')
|
+makeExcerpt(_appModuleTsVsMainTs, 'in-mem-web-api', '')
|
||||||
|
|
||||||
@ -169,15 +167,16 @@ block dont-be-distracted-by-backend-subst
|
|||||||
This chapter is an introduction to the !{_Angular_http_library}.
|
This chapter is an introduction to the !{_Angular_http_library}.
|
||||||
Please don't be distracted by the details of this backend substitution. Just follow along with the example.
|
Please don't be distracted by the details of this backend substitution. Just follow along with the example.
|
||||||
|
|
||||||
本章主要是介绍Angular的HTTP库,不要因为这种“替换后端”的细节而分心。先不要管为什么,只管照着这个例子做就可以了。
|
本章主要是介绍 Angular 的 HTTP 库,不要因为这种“替换后端”的细节而分心。
|
||||||
|
先不要管为什么,只管照着这个例子做就可以了。
|
||||||
|
|
||||||
Learn more later about the in-memory web API in the [HTTP client chapter](../guide/server-communication.html#in-mem-web-api).
|
Learn more later about the in-memory web API in the [HTTP client chapter](../guide/server-communication.html#in-mem-web-api).
|
||||||
Remember, the in-memory web API is only useful in the early stages of development and for demonstrations such as this Tour of Heroes.
|
Remember, the in-memory web API is only useful in the early stages of development and for demonstrations such as this Tour of Heroes.
|
||||||
Skip it when you have a real web API server.
|
Skip it when you have a real web API server.
|
||||||
|
|
||||||
要学习关于*内存Web API*的更多知识,请参阅[HTTP客户端](../guide/server-communication.html#in-mem-web-api)一章。
|
关于*内存 Web API* 的更多信息,见 [HTTP 客户端](../guide/server-communication.html#in-mem-web-api)。
|
||||||
记住,*内存 Web API* 主要用于开发的早期阶段或《英雄指南》这样的演示程序。
|
记住,*内存 Web API* 主要用于开发的早期阶段或《英雄指南》这样的演示程序。
|
||||||
如果你已经有了一个真实的Web API服务器,请尽管跳过它。
|
如果你已经有了一个真实的 Web API 服务器,尽管跳过它。
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
@ -196,8 +195,9 @@ block dont-be-distracted-by-backend-subst
|
|||||||
It may have seemed like overkill at the time, but we were anticipating the
|
It may have seemed like overkill at the time, but we were anticipating the
|
||||||
day when we fetched heroes with an HTTP client and we knew that would have to be an asynchronous operation.
|
day when we fetched heroes with an HTTP client and we knew that would have to be an asynchronous operation.
|
||||||
|
|
||||||
我们返回一个承诺(Promise),它用mock版的英雄列表进行解析。
|
我们返回一个承诺 (Promise),它用模拟版的英雄列表进行解析。
|
||||||
它当时可能看起来显得有点过于复杂,不过我们早就预料到总有这么一天会通过一个HTTP客户端来获取英雄数据,而且我们知道,那一定是一个异步操作。
|
它当时可能看起来显得有点过于复杂,不过我们预料到总有这么一天会通过 HTTP 客户端来获取英雄数据,
|
||||||
|
而且我们知道,那一定是一个异步操作。
|
||||||
|
|
||||||
That day has arrived! Let's convert `getHeroes()` to use HTTP.
|
That day has arrived! Let's convert `getHeroes()` to use HTTP.
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ block dont-be-distracted-by-backend-subst
|
|||||||
Refresh the browser, and the hero data should be successfully loaded from the
|
Refresh the browser, and the hero data should be successfully loaded from the
|
||||||
mock server.
|
mock server.
|
||||||
|
|
||||||
刷新浏览器后,英雄数据就会从Mock服务器被成功读取。
|
刷新浏览器后,英雄数据就会从模拟服务器被成功读取。
|
||||||
|
|
||||||
<h3 id="!{_h3id}">HTTP !{_Promise}</h3>
|
<h3 id="!{_h3id}">HTTP !{_Promise}</h3>
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ block get-heroes-details
|
|||||||
We'll learn about [Observables](#observables) later in this chapter.
|
We'll learn about [Observables](#observables) later in this chapter.
|
||||||
|
|
||||||
Angular 的`http.get`返回一个 RxJS 的`Observable`对象。
|
Angular 的`http.get`返回一个 RxJS 的`Observable`对象。
|
||||||
*Observable(可观察对象)*是一个管理异步数据流的强力方式。
|
*Observable(可观察对象)*是一个管理异步数据流的强力方式。
|
||||||
后面我们还会进一步学习[可观察对象](#observables)。
|
后面我们还会进一步学习[可观察对象](#observables)。
|
||||||
|
|
||||||
For *now* we get back on familiar ground by immediately
|
For *now* we get back on familiar ground by immediately
|
||||||
@ -319,7 +319,7 @@ block get-heroes-details
|
|||||||
We must anticipate HTTP failures as they happen frequently for reasons beyond our control.
|
We must anticipate HTTP failures as they happen frequently for reasons beyond our control.
|
||||||
|
|
||||||
这是一个关键的步骤!
|
这是一个关键的步骤!
|
||||||
我们必须预料到http请求会失败,因为有太多我们无法控制的原因可能导致它们频繁出现各种错误。
|
我们必须预料到 HTTP 请求会失败,因为有太多我们无法控制的原因可能导致它们频繁出现各种错误。
|
||||||
|
|
||||||
+makeExcerpt('app/hero.service.ts', 'handleError', '')
|
+makeExcerpt('app/hero.service.ts', 'handleError', '')
|
||||||
|
|
||||||
@ -332,7 +332,8 @@ block get-heroes-details
|
|||||||
We've also decided to return a user friendly form of the error to
|
We've also decided to return a user friendly form of the error to
|
||||||
the caller in a !{rejected_promise} so that the caller can display a proper error message to the user.
|
the caller in a !{rejected_promise} so that the caller can display a proper error message to the user.
|
||||||
|
|
||||||
我们还要通过一个被拒绝(rejected)的承诺(promise)来把该错误用一个用户友好的格式返回给调用者,以便调用者能把一个合适的错误信息显示给用户。
|
我们还要通过一个被拒绝 (rejected) 的承诺来把该错误用一个用户友好的格式返回给调用者,
|
||||||
|
以便调用者能把一个合适的错误信息显示给用户。
|
||||||
|
|
||||||
### Unchanged `getHeroes` API
|
### Unchanged `getHeroes` API
|
||||||
|
|
||||||
@ -376,7 +377,7 @@ block get-heroes-details
|
|||||||
the server.
|
the server.
|
||||||
|
|
||||||
以前是不会丢失更新的,现在是怎么回事?
|
以前是不会丢失更新的,现在是怎么回事?
|
||||||
当该应用使用mock出来的英雄列表时,修改的是一份全局共享的英雄列表,而现在改成了从服务器获取数据。
|
当该应用使用模拟出来的英雄列表时,修改的是一份全局共享的英雄列表,而现在改成了从服务器获取数据。
|
||||||
如果我们希望这些更改被持久化,我们就得把它们写回服务器。
|
如果我们希望这些更改被持久化,我们就得把它们写回服务器。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -448,7 +449,7 @@ block get-heroes-details
|
|||||||
In response to a click event, we call the component's click handler and then
|
In response to a click event, we call the component's click handler and then
|
||||||
clear the input field so that it will be ready to use for another name.
|
clear the input field so that it will be ready to use for another name.
|
||||||
|
|
||||||
当click事件触发时,我们调用组件的click处理器,然后清空这个输入框,以便用来输入另一个名字。
|
当点击事件触发时,我们调用组件的点击处理器,然后清空这个输入框,以便用来输入另一个名字。
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.ts', 'add')
|
+makeExcerpt('app/heroes.component.ts', 'add')
|
||||||
|
|
||||||
@ -456,7 +457,8 @@ block get-heroes-details
|
|||||||
When the given name is non-blank, the handler delegates creation of the
|
When the given name is non-blank, the handler delegates creation of the
|
||||||
named hero to the hero service, and then adds the new hero to our !{_array}.
|
named hero to the hero service, and then adds the new hero to our !{_array}.
|
||||||
|
|
||||||
当指定的名字不为空的时候,click处理器就会委托hero服务来创建一个具有此名字的英雄,并把这个新的英雄添加到我们的数组中。
|
当指定的名字不为空的时候,点击处理器就会委托 hero 服务来创建一个具有此名字的英雄,
|
||||||
|
并把这个新的英雄添加到我们的数组中。
|
||||||
|
|
||||||
Finally, we implement the `create` method in the `HeroService` class.
|
Finally, we implement the `create` method in the `HeroService` class.
|
||||||
|
|
||||||
@ -484,7 +486,7 @@ block get-heroes-details
|
|||||||
Add this button element to the heroes component HTML, right after the hero
|
Add this button element to the heroes component HTML, right after the hero
|
||||||
name in the repeated `<li>` tag:
|
name in the repeated `<li>` tag:
|
||||||
|
|
||||||
把这个button元素添加到英雄列表组件的HTML中,把它放在`<li>`标签中的英雄名的后面:
|
把这个按钮元素添加到英雄列表组件的 HTML 中,把它放在`<li>`标签中的英雄名的后面:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.html', 'delete', '')
|
+makeExcerpt('app/heroes.component.html', 'delete', '')
|
||||||
|
|
||||||
@ -501,7 +503,8 @@ block get-heroes-details
|
|||||||
don't want the `<li>` click handler to be triggered because that would
|
don't want the `<li>` click handler to be triggered because that would
|
||||||
select the hero that we are going to delete!
|
select the hero that we are going to delete!
|
||||||
|
|
||||||
除了调用组件的`delete`方法之外,这个`delete`按钮的click处理器还应该阻止click事件向上冒泡 —— 我们并不希望触发`<li>`的事件处理器,否则它会选中我们要删除的这位英雄。
|
除了调用组件的`delete`方法之外,这个`delete`按钮的点击处理器还应该阻止点击事件向上冒泡 —
|
||||||
|
我们并不希望触发`<li>`的事件处理器,否则它会选中我们要删除的这位英雄。
|
||||||
|
|
||||||
The logic of the `delete` handler is a bit trickier:
|
The logic of the `delete` handler is a bit trickier:
|
||||||
|
|
||||||
@ -514,7 +517,8 @@ block get-heroes-details
|
|||||||
is still responsible for updating the display: it removes the deleted hero
|
is still responsible for updating the display: it removes the deleted hero
|
||||||
from the !{_array} and resets the selected hero if necessary.
|
from the !{_array} and resets the selected hero if necessary.
|
||||||
|
|
||||||
当然,我们仍然把删除英雄的操作委托给了hero服务,不过该组件仍然负责更新显示:它从数组中移除了被删除的英雄,如果删除的是正选中的英雄,还会清空选择。
|
当然,我们仍然把删除英雄的操作委托给了 hero 服务,
|
||||||
|
不过该组件仍然负责更新显示:它从数组中移除了被删除的英雄,如果删除的是正选中的英雄,还会清空选择。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We want our delete button to be placed at the far right of the hero entry.
|
We want our delete button to be placed at the far right of the hero entry.
|
||||||
@ -545,7 +549,7 @@ block get-heroes-details
|
|||||||
:marked
|
:marked
|
||||||
## !{_Observable}s
|
## !{_Observable}s
|
||||||
|
|
||||||
## 可观察对象(Observable)
|
## 可观察对象 (Observable)
|
||||||
|
|
||||||
block observables-section-intro
|
block observables-section-intro
|
||||||
:marked
|
:marked
|
||||||
@ -566,7 +570,7 @@ block observables-section-intro
|
|||||||
|
|
||||||
An *observable* is a stream of events that we can process with array-like operators.
|
An *observable* is a stream of events that we can process with array-like operators.
|
||||||
|
|
||||||
一个*可观察对象*是一个事件流,我们可以用数组型操作符(函数)来处理它。
|
一个*可观察对象*是一个事件流,我们可以用数组型操作符来处理它。
|
||||||
|
|
||||||
Angular core has basic support for observables. We developers augment that support with
|
Angular core has basic support for observables. We developers augment that support with
|
||||||
operators and extensions from the [RxJS Observables](http://reactivex.io/rxjs/) library.
|
operators and extensions from the [RxJS Observables](http://reactivex.io/rxjs/) library.
|
||||||
@ -595,7 +599,8 @@ block observables-section-intro
|
|||||||
Such a _request-cancel-new-request_ sequence is difficult to implement with *!{_Promise}s*.
|
Such a _request-cancel-new-request_ sequence is difficult to implement with *!{_Promise}s*.
|
||||||
It's easy with *!{_Observable}s* as we'll see.
|
It's easy with *!{_Observable}s* as we'll see.
|
||||||
|
|
||||||
但是请求并非总是“一次性”的。我们可以开始一个请求,并且取消它,再开始另一个不同的请求 —— 在服务器对第一个请求作出回应之前。
|
但是请求并非总是“一次性”的。我们可以开始一个请求,
|
||||||
|
并且取消它,在服务器对第一个请求作出回应之前,再开始另一个不同的请求 。
|
||||||
像这样一个_请求-取消-新请求_的序列用*承诺*是很难实现的,但接下来我们会看到,它对于*可观察对象*却很简单。
|
像这样一个_请求-取消-新请求_的序列用*承诺*是很难实现的,但接下来我们会看到,它对于*可观察对象*却很简单。
|
||||||
|
|
||||||
### Search-by-name
|
### Search-by-name
|
||||||
@ -723,17 +728,20 @@ block observable-transformers
|
|||||||
* `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds
|
* `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds
|
||||||
before passing along the latest string. We'll never make requests more frequently than 300ms.
|
before passing along the latest string. We'll never make requests more frequently than 300ms.
|
||||||
|
|
||||||
* 在传出最终字符串之前,`debounceTime(300)`将会等待,直到新增字符串的事件暂停了300毫秒。我们实际发起请求的间隔永远不会小于300ms。
|
在传出最终字符串之前,`debounceTime(300)`将会等待,直到新增字符串的事件暂停了 300 毫秒。
|
||||||
|
我们实际发起请求的间隔永远不会小于 300ms。
|
||||||
|
|
||||||
* `distinctUntilChanged` ensures that we only send a request if the filter text changed.
|
* `distinctUntilChanged` ensures that we only send a request if the filter text changed.
|
||||||
There's no point in repeating a request for the same search term.
|
There's no point in repeating a request for the same search term.
|
||||||
|
|
||||||
* `distinctUntilChanged`确保只在过滤条件变化时才发送请求,这样就不会重复请求同一个搜索词了。
|
`distinctUntilChanged`确保只在过滤条件变化时才发送请求,
|
||||||
|
这样就不会重复请求同一个搜索词了。
|
||||||
|
|
||||||
* `switchMap` calls our search service for each search term that makes it through the `debounce` and `distinctUntilChanged` gauntlet.
|
* `switchMap` calls our search service for each search term that makes it through the `debounce` and `distinctUntilChanged` gauntlet.
|
||||||
It cancels and discards previous search observables, returning only the latest search service observable.
|
It cancels and discards previous search observables, returning only the latest search service observable.
|
||||||
|
|
||||||
* `switchMap`会为每个从`debounce`和`distinctUntilChanged`中通过的搜索词调用搜索服务。它会取消并丢弃以前的搜索可观察对象,只保留最近的。
|
`switchMap`会为每个从`debounce`和`distinctUntilChanged`中通过的搜索词调用搜索服务。
|
||||||
|
它会取消并丢弃以前的搜索可观察对象,只保留最近的。
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
@ -747,13 +755,14 @@ block observable-transformers
|
|||||||
Even with a 300ms pause between requests, we could have multiple HTTP requests in flight
|
Even with a 300ms pause between requests, we could have multiple HTTP requests in flight
|
||||||
and they may not return in the order sent.
|
and they may not return in the order sent.
|
||||||
|
|
||||||
每次符合条件的按键事件都会触发一次对`http`方法的调用。即使在发送每个请求前都有300毫秒的延迟,我们仍然可能同时拥有多个在途的HTTP请求,并且它们返回的顺序未必就是发送时的顺序。
|
每次符合条件的按键事件都会触发一次对`http`方法的调用。即使在发送每个请求前都有 300 毫秒的延迟,
|
||||||
|
我们仍然可能同时拥有多个在途的 HTTP 请求,并且它们返回的顺序未必就是发送时的顺序。
|
||||||
|
|
||||||
`switchMap` preserves the original request order while returning
|
`switchMap` preserves the original request order while returning
|
||||||
only the observable from the most recent `http` method call.
|
only the observable from the most recent `http` method call.
|
||||||
Results from prior calls are canceled and discarded.
|
Results from prior calls are canceled and discarded.
|
||||||
|
|
||||||
`switchMap`保留了原始的请求顺序,并且只返回最近一次http调用返回的可观察对象。
|
`switchMap`保留了原始的请求顺序,并且只返回最近一次 `http` 调用返回的可观察对象。
|
||||||
这是因为以前的调用都被取消或丢弃了。
|
这是因为以前的调用都被取消或丢弃了。
|
||||||
|
|
||||||
We also short-circuit the `http` method call and return an observable containing an empty array
|
We also short-circuit the `http` method call and return an observable containing an empty array
|
||||||
@ -765,7 +774,8 @@ block observable-transformers
|
|||||||
until the service supports that feature, a topic for another day.
|
until the service supports that feature, a topic for another day.
|
||||||
We are content for now to discard unwanted results.
|
We are content for now to discard unwanted results.
|
||||||
|
|
||||||
注意,_取消_`HeroSearchService`的可观察对象并不会实际中止(abort)一个未完成的HTTP请求,除非服务支持这个特性,这个问题我们以后再讨论。
|
注意,_取消_`HeroSearchService`的可观察对象并不会实际中止 (abort) 一个未完成的 HTTP 请求,
|
||||||
|
除非服务支持这个特性,这个问题我们以后再讨论。
|
||||||
目前我们的做法只是丢弃不希望的结果。
|
目前我们的做法只是丢弃不希望的结果。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
@ -788,7 +798,8 @@ block observable-transformers
|
|||||||
We could extend `Observable` with just the operators we need here by
|
We could extend `Observable` with just the operators we need here by
|
||||||
including the pertinent `import` statements at the top of this file.
|
including the pertinent `import` statements at the top of this file.
|
||||||
|
|
||||||
通过在本文件的顶部写上适当的`import`语句,我们可以为`Observable`扩展出这里用到的那些操作符。
|
通过在本文件的顶部写上适当的`import`语句,
|
||||||
|
我们可以为`Observable`扩展出这里用到的那些操作符。
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
@ -903,27 +914,27 @@ block filetree
|
|||||||
|
|
||||||
- We added the necessary dependencies to use HTTP in our application.
|
- We added the necessary dependencies to use HTTP in our application.
|
||||||
|
|
||||||
- 我们添加了在应用程序中使用HTTP的必备依赖。
|
我们添加了在应用程序中使用 HTTP 的必备依赖。
|
||||||
|
|
||||||
- We refactored `HeroService` to load heroes from a web API.
|
- We refactored `HeroService` to load heroes from a web API.
|
||||||
|
|
||||||
- 我们重构了`HeroService`,以通过web API来加载英雄数据。
|
我们重构了`HeroService`,以通过 web API 来加载英雄数据。
|
||||||
|
|
||||||
- We extended `HeroService` to support post, put and delete methods.
|
- We extended `HeroService` to support post, put and delete methods.
|
||||||
|
|
||||||
- 我们扩展了`HeroService`来支持post、put和delete方法。
|
我们扩展了`HeroService`来支持 post、put 和 delete 方法。
|
||||||
|
|
||||||
- We updated our components to allow adding, editing and deleting of heroes.
|
- We updated our components to allow adding, editing and deleting of heroes.
|
||||||
|
|
||||||
- 我们更新了组件,以允许用户添加、编辑和删除英雄。
|
我们更新了组件,以允许用户添加、编辑和删除英雄。
|
||||||
|
|
||||||
- We configured an in-memory web API.
|
- We configured an in-memory web API.
|
||||||
|
|
||||||
- 我们配置了一个内存Web API。
|
我们配置了一个内存 Web API。
|
||||||
|
|
||||||
- We learned how to use !{_Observable}s.
|
- We learned how to use !{_Observable}s.
|
||||||
|
|
||||||
- 我们学会了如何使用“可观察对象”。
|
我们学会了如何使用“可观察对象”。
|
||||||
|
|
||||||
Here are the files we _added or changed_ in this chapter.
|
Here are the files we _added or changed_ in this chapter.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user