对上次的合并查漏补缺
This commit is contained in:
parent
ab06793705
commit
8a7165acf5
|
@ -721,7 +721,7 @@ block hero-list-comp-add-hero
|
||||||
It's easy to do and a promise-based version looks much like the observable-based version in simple cases.
|
It's easy to do and a promise-based version looks much like the observable-based version in simple cases.
|
||||||
|
|
||||||
虽然Angular的`http`客户端API返回的是`Observable<Response>`类型的对象,但我们也可以把它转成
|
虽然Angular的`http`客户端API返回的是`Observable<Response>`类型的对象,但我们也可以把它转成
|
||||||
[Promise<Response>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
[`Promise<Response>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。
|
||||||
这很容易,并且在简单的场景中,一个基于承诺(Promise)的版本看起来很像基于可观察对象(Observable)的版本。
|
这很容易,并且在简单的场景中,一个基于承诺(Promise)的版本看起来很像基于可观察对象(Observable)的版本。
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
|
|
|
@ -698,8 +698,8 @@ p.
|
||||||
|
|
||||||
p.
|
p.
|
||||||
<code>app.component.html</code>显示了这个可下载的Angular Logo
|
<code>app.component.html</code>显示了这个可下载的Angular Logo
|
||||||
<a href="https://raw.githubusercontent.com/angular/angular.io/master/public/resources/images/logos/angular2/angular.png" target="_blank">
|
<a href="/resources/images/logos/angular2/angular.png" target="_blank">
|
||||||
<img src="https://raw.githubusercontent.com/angular/angular.io/master/public/resources/images/logos/angular2/angular.png" height="40px" title="download Angular logo"></a>。
|
<img src="/resources/images/logos/angular2/angular.png" height="40px" title="download Angular logo"></a>。
|
||||||
|
|
||||||
+makeTabs(
|
+makeTabs(
|
||||||
`webpack/ts/src/vendor.ts,
|
`webpack/ts/src/vendor.ts,
|
||||||
|
|
|
@ -17,8 +17,7 @@ block includes
|
||||||
guides.
|
guides.
|
||||||
|
|
||||||
这份“快速起步”的目标是基于#{_Lang}构建并运行一个超级简单的Angular应用,
|
这份“快速起步”的目标是基于#{_Lang}构建并运行一个超级简单的Angular应用,
|
||||||
并为文档其余部分的范例代码建立开发环境。
|
同时,它还会建立一个用于本指南中这些范例代码的公用开发环境。
|
||||||
同时,它还可以作为构建真实应用的基础。
|
|
||||||
|
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
header Don't want #{_Lang}?
|
header Don't want #{_Lang}?
|
||||||
|
@ -291,68 +290,104 @@ block install-packages
|
||||||
:marked
|
:marked
|
||||||
Create the file `app/app.module.ts` with the following content:
|
Create the file `app/app.module.ts` with the following content:
|
||||||
|
|
||||||
|
使用下列内容创建`app/app.module.ts`文件:
|
||||||
|
|
||||||
+makeExample('app/app.module.1.ts')(format='.')
|
+makeExample('app/app.module.1.ts')(format='.')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
This is the entry point to your application.
|
This is the entry point to your application.
|
||||||
|
|
||||||
|
这里是应用的入口点。
|
||||||
|
|
||||||
Since the QuickStart application is a web application that runs in a browser, your root module
|
Since the QuickStart application is a web application that runs in a browser, your root module
|
||||||
needs to import the
|
needs to import the
|
||||||
[`BrowserModule`](../latest/api/platform-browser/index/BrowserModule-class.html)
|
[`BrowserModule`](../latest/api/platform-browser/index/BrowserModule-class.html)
|
||||||
from `@angular/platform-browser` to the `imports` array.
|
from `@angular/platform-browser` to the `imports` array.
|
||||||
|
|
||||||
|
由于QuickStart是一个运行在浏览器中的Web应用,所以根模块需要从`@angular/platform-browser`中导入[`BrowserModule`](../latest/api/platform-browser/index/BrowserModule-class.html)并添加到`imports`数组中。
|
||||||
|
|
||||||
This is the smallest amount of Angular that is needed for a minimal application to run in the
|
This is the smallest amount of Angular that is needed for a minimal application to run in the
|
||||||
browser.
|
browser.
|
||||||
|
|
||||||
|
这是要让一个最小的应用在浏览器中运行时,对Angular的最低需求。
|
||||||
|
|
||||||
The QuickStart application doesn't do anything else, so you don't need any other modules. In a real
|
The QuickStart application doesn't do anything else, so you don't need any other modules. In a real
|
||||||
application, you'd likely import [`FormsModule`](../latest/api/forms/index/FormsModule-class
|
application, you'd likely import [`FormsModule`](../latest/api/forms/index/FormsModule-class
|
||||||
.html) as well as [`RouterModule`](../latest/api/router/index/RouterModule-class.html) and
|
.html) as well as [`RouterModule`](../latest/api/router/index/RouterModule-class.html) and
|
||||||
[`HttpModule`](../latest/api/http/index/HttpModule-class.html). These are introduced in the
|
[`HttpModule`](../latest/api/http/index/HttpModule-class.html). These are introduced in the
|
||||||
[Tour of Heroes Tutorial](../tutorial/).
|
[Tour of Heroes Tutorial](../tutorial/).
|
||||||
|
|
||||||
|
QuickStart应用不做别的,也就先不需要其他模块。在真实的应用中,我们可能还得导入[`FormsModule`](../latest/api/forms/index/FormsModule-class
|
||||||
|
.html)、[`RouterModule`](../latest/api/router/index/RouterModule-class.html)和
|
||||||
|
[`HttpModule`](../latest/api/http/index/HttpModule-class.html)。这些会在[英雄指南教程](../tutorial/)中引入。
|
||||||
|
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
h1#root-component Step !{step++}: Create a component and add it to your application
|
h1#root-component Step !{step++}: Create a component and add it to your application
|
||||||
|
h1#root-component 步骤3:创建组件并添加到应用中
|
||||||
:marked
|
:marked
|
||||||
Every Angular application has at least one component: the _root component_, named `AppComponent`
|
Every Angular application has at least one component: the _root component_, named `AppComponent`
|
||||||
here.
|
here.
|
||||||
|
|
||||||
|
每个Angular应用都至少有一个组件:*根组件*,这里名叫`AppComponent`。
|
||||||
|
|
||||||
Components are the basic building blocks of Angular applications. A component controls a portion
|
Components are the basic building blocks of Angular applications. A component controls a portion
|
||||||
of the screen—a *view*—through its associated template.
|
of the screen—a *view*—through its associated template.
|
||||||
|
|
||||||
|
组件是Angualr应用的基本构造块。每个组件都会通过与它相关的模板来控制屏幕上的一小块(视图)。
|
||||||
|
|
||||||
a#app-component
|
a#app-component
|
||||||
p.
|
p.
|
||||||
#[b Create the component file]
|
#[b Create the component file]
|
||||||
#[code #[+adjExPath('app/app.component.ts')]] with the following content:
|
#[code #[+adjExPath('app/app.component.ts')]] with the following content:
|
||||||
|
|
||||||
|
p.
|
||||||
|
#[b 使用下列内容创建组件文件]
|
||||||
|
#[code #[+adjExPath('app/app.component.ts')]]:
|
||||||
|
|
||||||
+makeExample('app/app.component.ts')
|
+makeExample('app/app.component.ts')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The QuickStart application has the same essential structure as any other Angular component:
|
The QuickStart application has the same essential structure as any other Angular component:
|
||||||
|
|
||||||
|
QuickStart应用具有和其它Angular组件相同的基本结构:
|
||||||
|
|
||||||
* **An import statement**. Importing gives your component access to
|
* **An import statement**. Importing gives your component access to
|
||||||
Angular's core [`@Component` decorator function](../latest/api/core/index/Component-decorator
|
Angular's core [`@Component` decorator function](../latest/api/core/index/Component-decorator
|
||||||
.html).
|
.html).
|
||||||
|
* **一个import语句**。它让你能访问Angular核心库中的[`@Component`装饰器函数](../latest/api/core/index/Component-decorator.html)。
|
||||||
* **A @Component #{_decorator}** that associates *metadata* with the
|
* **A @Component #{_decorator}** that associates *metadata* with the
|
||||||
`AppComponent` component class:
|
`AppComponent` component class:
|
||||||
|
* **一个@Component#{_decoratorCn}**,它会把一份*元数据*关联到`AppComponent`组件类上:
|
||||||
|
|
||||||
- a *selector* that specifies a simple CSS selector for an HTML element that represents
|
- a *selector* that specifies a simple CSS selector for an HTML element that represents
|
||||||
the component.
|
the component.
|
||||||
|
- *selector*为用来代表该组件的HTML元素指定一个简单的CSS选择器。
|
||||||
- a *template* that tells Angular how to render the component's view.
|
- a *template* that tells Angular how to render the component's view.
|
||||||
|
- *template*用来告诉Angular如何渲染该组件的视图。
|
||||||
* **A component class** that controls the appearance and behavior of a view
|
* **A component class** that controls the appearance and behavior of a view
|
||||||
|
* **组件类**通过它的模板来控制视图的外观和行为
|
||||||
|
|
||||||
through its template. Here, you only have the root component, `AppComponent`. Since you don't
|
through its template. Here, you only have the root component, `AppComponent`. Since you don't
|
||||||
need any application logic in the simple QuickStart example, it's empty.
|
need any application logic in the simple QuickStart example, it's empty.
|
||||||
|
|
||||||
|
这里,你只有一个根组件`AppComponent`。由于这个简单的QuickStart范例中并不需要应用逻辑,因此它是空的。
|
||||||
|
|
||||||
You *export* the `AppComponent` class so that you can *import* it into the application that you
|
You *export* the `AppComponent` class so that you can *import* it into the application that you
|
||||||
just created.
|
just created.
|
||||||
|
|
||||||
|
我们还要*导出*这个`AppComponent`类,以便让刚刚创建的这个应用导入它。
|
||||||
|
|
||||||
Edit the file `app/app.module.ts` to import your new `AppComponent` and add it in the
|
Edit the file `app/app.module.ts` to import your new `AppComponent` and add it in the
|
||||||
declarations and bootstrap fields in the `NgModule` decorator:
|
declarations and bootstrap fields in the `NgModule` decorator:
|
||||||
|
|
||||||
|
编辑`app/app.module.ts`文件,导入这个新的`AppComponent`,并把它添加到`NgModule`装饰器中的`declarations`和`bootstrap`字段:
|
||||||
|
|
||||||
+makeExample('app/app.module.ts', null, title='app/app.module.ts')
|
+makeExample('app/app.module.ts', null, title='app/app.module.ts')
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
h1#main Step !{step++}: Start up your application
|
h1#main Step !{step++}: Start up your application
|
||||||
|
h1#main 步骤4:启动应用
|
||||||
|
|
||||||
block create-main
|
block create-main
|
||||||
:marked
|
:marked
|
||||||
|
@ -373,14 +408,21 @@ block create-main
|
||||||
This code initializes the platform that your application runs in, then uses the platform to
|
This code initializes the platform that your application runs in, then uses the platform to
|
||||||
bootstrap your `!{_AppModuleVsAppComp}`.
|
bootstrap your `!{_AppModuleVsAppComp}`.
|
||||||
|
|
||||||
|
这些代码初始化了应用所在的平台,然后使用此平台引导你的`!{_AppModuleVsAppComp}`。
|
||||||
|
|
||||||
### Why create separate *<span ngio-ex>main.ts</span>*<span if-docs="ts">, app module</span> and app component files?
|
### Why create separate *<span ngio-ex>main.ts</span>*<span if-docs="ts">, app module</span> and app component files?
|
||||||
|
|
||||||
|
### 为什么要分别创建*<span ngio-ex>main.ts</span>*<span if-docs="ts">、应用模块</span>和应用组件的文件呢?
|
||||||
|
|
||||||
App bootstrapping is a separate concern from<span if-docs="ts"> creating a module or</span>
|
App bootstrapping is a separate concern from<span if-docs="ts"> creating a module or</span>
|
||||||
presenting a view. Testing the component is much easier if it doesn't also try to run the entire application.
|
presenting a view. Testing the component is much easier if it doesn't also try to run the entire application.
|
||||||
|
|
||||||
|
应用的引导过程与<span if-docs="ts">创建模块或者</span>展现视图是相互独立的关注点。如果该组件不会试图运行整个应用,那么测试它就会更容易。
|
||||||
|
|
||||||
|
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
header Bootstrapping is platform-specific
|
header Bootstrapping is platform-specific
|
||||||
|
header 引导过程是与平台有关的
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Because the QuickStart application runs directly in the browser, `main.ts` imports the
|
Because the QuickStart application runs directly in the browser, `main.ts` imports the
|
||||||
|
@ -399,6 +441,7 @@ block create-main
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
h1#index Step !{step++}: Define the web page that hosts the application
|
h1#index Step !{step++}: Define the web page that hosts the application
|
||||||
|
h1#index 步骤5:定义该应用的宿主页面
|
||||||
:marked
|
:marked
|
||||||
In the *#{_indexHtmlDir}* folder,
|
In the *#{_indexHtmlDir}* folder,
|
||||||
create an `index.html` file and paste the following lines into it:
|
create an `index.html` file and paste the following lines into it:
|
||||||
|
@ -412,22 +455,34 @@ h1#index Step !{step++}: Define the web page that hosts the application
|
||||||
:marked
|
:marked
|
||||||
The noteworthy sections here are:
|
The noteworthy sections here are:
|
||||||
|
|
||||||
|
这里值得注意的地方有:
|
||||||
|
|
||||||
* JavaScript libraries: `core-js` polyfills for older browsers, the `zone.js` and
|
* JavaScript libraries: `core-js` polyfills for older browsers, the `zone.js` and
|
||||||
`reflect-metadata` libraries needed by Angular, and the `SystemJS` library for module loading.
|
`reflect-metadata` libraries needed by Angular, and the `SystemJS` library for module loading.
|
||||||
|
* JavaScript库:`core-js`是为老式浏览器提供的填充库,`zone.js`和`reflect-metadata`库是Angular需要的,而`SystemJS`库是用来做模块加载的。
|
||||||
* Configuration file for `SystemJS`, and a script
|
* Configuration file for `SystemJS`, and a script
|
||||||
where you import and run the `app` module which refers to the `main` file that you just
|
where you import and run the `app` module which refers to the `main` file that you just
|
||||||
wrote.
|
wrote.
|
||||||
|
* `SystemJS`的配置文件和一段脚本,它导入并运行了我们刚刚在`main`文件中写的`app`模块。
|
||||||
* The [`<my-app>`](#my-app) tag in the `<body>` which is *where your app lives!*
|
* The [`<my-app>`](#my-app) tag in the `<body>` which is *where your app lives!*
|
||||||
|
* `<body>`中的[`<my-app>`](#my-app)标签是*应用程序生活的地方!*
|
||||||
|
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
## Add some style
|
## Add some style
|
||||||
|
|
||||||
|
## 添加一些样式
|
||||||
|
|
||||||
Styles aren't essential, but they're nice, and `index.html` assumes that you have
|
Styles aren't essential, but they're nice, and `index.html` assumes that you have
|
||||||
a stylesheet called `styles.css`.
|
a stylesheet called `styles.css`.
|
||||||
|
|
||||||
|
样式不是必须的,但能让应用更漂亮。`index.html`中假定有一个叫做`styles.css`的样式表。
|
||||||
|
|
||||||
Create a `styles.css` file in the *#{_indexHtmlDir}* folder, and start styling,
|
Create a `styles.css` file in the *#{_indexHtmlDir}* folder, and start styling,
|
||||||
perhaps with the minimal styles shown below.
|
perhaps with the minimal styles shown below.
|
||||||
|
|
||||||
|
在*#{_indexHtmlDir}*目录下创建一个`style.css`文件,并且用下面列出的最小化样式作为初始样式。
|
||||||
|
|
||||||
+makeExcerpt('styles.css (excerpt)', 'quickstart')
|
+makeExcerpt('styles.css (excerpt)', 'quickstart')
|
||||||
|
|
||||||
.callout.is-helpful
|
.callout.is-helpful
|
||||||
|
@ -452,11 +507,18 @@ aside.is-right
|
||||||
[Read more](https://github.com/angular/quickstart/blob/master/README.md#npm-scripts) about
|
[Read more](https://github.com/angular/quickstart/blob/master/README.md#npm-scripts) about
|
||||||
other useful npm scripts included in this example's `package.json`.
|
other useful npm scripts included in this example's `package.json`.
|
||||||
|
|
||||||
|
到[这里](https://github.com/angular/quickstart/blob/master/README.md#npm-scripts)了解更多关于`package.json`中其它脚本的知识。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
That command runs the following two parallel node processes:
|
That command runs the following two parallel node processes:
|
||||||
|
|
||||||
|
该命令会同时运行两个并行的node进程:
|
||||||
|
|
||||||
* The TypeScript compiler in watch mode.
|
* The TypeScript compiler in watch mode.
|
||||||
|
* TypeScript编译器运行在监听模式。
|
||||||
* A static file server called _lite-server_ that loads `index.html` in a browser
|
* A static file server called _lite-server_ that loads `index.html` in a browser
|
||||||
and refreshes the browser when application files change.
|
and refreshes the browser when application files change.
|
||||||
|
* 一个名叫*lite-server*的静态文件服务器,它把`index.html`加载到浏览器中,并且在该应用中的文件发生变化时刷新浏览器。
|
||||||
|
|
||||||
In a few moments, a browser tab should open and display the following:
|
In a few moments, a browser tab should open and display the following:
|
||||||
|
|
||||||
|
@ -473,19 +535,27 @@ block build-app
|
||||||
h1 Step !{step++}: Make some live changes
|
h1 Step !{step++}: Make some live changes
|
||||||
:marked
|
:marked
|
||||||
Try changing the message in `app/app.component.ts` to "My SECOND Angular 2 App".
|
Try changing the message in `app/app.component.ts` to "My SECOND Angular 2 App".
|
||||||
|
|
||||||
|
尝试把`app/app.component.ts`中的消息修改成"My SECOND Angular 2 App"。
|
||||||
|
|
||||||
block server-watching
|
block server-watching
|
||||||
:marked
|
:marked
|
||||||
The TypeScript compiler and `lite-server` will detect your change, recompile the TypeScript into JavaScript,
|
The TypeScript compiler and `lite-server` will detect your change, recompile the TypeScript into JavaScript,
|
||||||
refresh the browser, and display your revised message.
|
refresh the browser, and display your revised message.
|
||||||
|
|
||||||
|
TypeScript编译器和`lite-server`将会检测这些修改,重新把TypeScript编译成JavaScript,刷新浏览器,并显示修改过的消息。
|
||||||
|
|
||||||
Close the terminal window when you're done to terminate both the compiler and the server.
|
Close the terminal window when you're done to terminate both the compiler and the server.
|
||||||
|
|
||||||
当终止了编译器和服务器之后,可以关闭terminal窗口。
|
当终止了编译器和服务器之后,可以关闭terminal窗口。
|
||||||
.l-main-section
|
.l-main-section
|
||||||
h1#wrap-up Wrap up and next steps
|
h1#wrap-up Wrap up and next steps
|
||||||
|
h1#wrap-up 收工,下一步
|
||||||
:marked
|
:marked
|
||||||
The final project folder structure looks like this:
|
The final project folder structure looks like this:
|
||||||
|
|
||||||
|
项目的最终目录结构看起来是这样的:
|
||||||
|
|
||||||
block project-file-structure
|
block project-file-structure
|
||||||
.filetree
|
.filetree
|
||||||
.file angular2-quickstart
|
.file angular2-quickstart
|
||||||
|
@ -506,20 +576,34 @@ block project-file-structure
|
||||||
:marked
|
:marked
|
||||||
To see the file contents, open the <live-example></live-example>.
|
To see the file contents, open the <live-example></live-example>.
|
||||||
|
|
||||||
|
要查看文件的内容,请打开<live-example></live-example>。
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## What next?
|
## What next?
|
||||||
|
## 下一步干什么?
|
||||||
|
|
||||||
This first application doesn't do much. It's basically "Hello, World" for Angular 2.
|
This first application doesn't do much. It's basically "Hello, World" for Angular 2.
|
||||||
|
|
||||||
|
第一个应用没做什么,它只是一个Angular 2的"Hello, World"而已。
|
||||||
|
|
||||||
You wrote a little Angular component, created a simple `index.html`, and launched with a
|
You wrote a little Angular component, created a simple `index.html`, and launched with a
|
||||||
static file server.
|
static file server.
|
||||||
|
|
||||||
|
我们写了一个很小的Angular组件,递减了一个简单的`index.html`,并且启动了一个静态文件服务器。
|
||||||
|
|
||||||
+ifDocsFor('ts')
|
+ifDocsFor('ts')
|
||||||
:marked
|
:marked
|
||||||
You also created the basic application setup that you'll re-use for other
|
You also created the basic application setup that you'll re-use for other
|
||||||
sections in this guide. From here, the changes you'll make in the
|
sections in this guide. From here, the changes you'll make in the
|
||||||
`package.json` or `index.html` files are only minor updates to add libraries or some css
|
`package.json` or `index.html` files are only minor updates to add libraries or some css
|
||||||
stylesheets. You also won't need to revisit module loading again.
|
stylesheets. You also won't need to revisit module loading again.
|
||||||
|
|
||||||
|
我们还设置了一个基本的应用环境,你可以把它用在本指南的其它部分。以后,我们对`package.json`和`index.html`的修改将仅限于添加库或一些css样式,不用再需要修改模块加载部分。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
To take the next step and build a small application that demonstrates real features that you can
|
To take the next step and build a small application that demonstrates real features that you can
|
||||||
build with Angular, carry on to the [Tour of Heroes tutorial](./tutorial)!
|
build with Angular, carry on to the [Tour of Heroes tutorial](./tutorial)!
|
||||||
|
|
||||||
|
下一步我们会开始构建一个小型的应用,用于示范能通过Angular构建的真实特性。
|
||||||
|
来吧!开始[“英雄指南”教程](./tutorial)!
|
||||||
|
|
|
@ -1108,6 +1108,8 @@ block extract-id
|
||||||
:marked
|
:marked
|
||||||
Delete the `<h1>` at the top (forgot about it during the `AppComponent`-to-`HeroesComponent` conversion).
|
Delete the `<h1>` at the top (forgot about it during the `AppComponent`-to-`HeroesComponent` conversion).
|
||||||
|
|
||||||
|
删除顶部的`<h1>`(在从`AppComponent`转到`HeroesComponent`期间可以先忘掉它)。
|
||||||
|
|
||||||
Delete the last line of the template with the `<my-hero-detail>` tags.
|
Delete the last line of the template with the `<my-hero-detail>` tags.
|
||||||
|
|
||||||
删除模板最后带有`<my-hero-detail>`标签的那一行。
|
删除模板最后带有`<my-hero-detail>`标签的那一行。
|
||||||
|
|
|
@ -72,7 +72,7 @@ block http-library
|
||||||
It's Angular's optional approach to web access and it exists as a separate add-on module called `@angular/http`,
|
It's Angular's optional approach to web access and it exists as a separate add-on module called `@angular/http`,
|
||||||
shipped in a separate script file as part of the Angular npm package.
|
shipped in a separate script file as part of the Angular npm package.
|
||||||
|
|
||||||
`Http`***并不是***Angular的核心模块。
|
`HttpModule`***并不是***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.
|
Fortunately we're ready to import from `@angular/http` because `systemjs.config` configured *SystemJS* to load that library when we need it.
|
||||||
|
@ -291,7 +291,7 @@ block get-heroes-details
|
||||||
|
|
||||||
仔细看看这个由服务器返回的数据的形态。
|
仔细看看这个由服务器返回的数据的形态。
|
||||||
这个*内存Web API*的范例中所做的是返回一个带有`data`属性的对象。
|
这个*内存Web API*的范例中所做的是返回一个带有`data`属性的对象。
|
||||||
你的API也可以返回其它东西。
|
你的API也可以返回其它东西。请调整这些代码以匹配*你的Web API*。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The caller is unaware of these machinations. It receives a !{_Promise} of *heroes* just as it did before.
|
The caller is unaware of these machinations. It receives a !{_Promise} of *heroes* just as it did before.
|
||||||
|
@ -357,9 +357,15 @@ block get-heroes-details
|
||||||
:marked
|
:marked
|
||||||
## Update hero details
|
## Update hero details
|
||||||
|
|
||||||
|
## 更新英雄详情
|
||||||
|
|
||||||
We can edit a hero's name already in the hero detail view. Go ahead and try
|
We can edit a hero's name already in the hero detail view. Go ahead and try
|
||||||
it. As we type, the hero name is updated in the view heading.
|
it. As we type, the hero name is updated in the view heading.
|
||||||
But when we hit the `Back` button, the changes are lost!
|
But when we hit the `Back` button, the changes are lost!
|
||||||
|
|
||||||
|
我们已经可以在英雄详情中编辑英雄的名字了。来试试吧。在输入的时候,页头上的英雄名字也会随之更新。
|
||||||
|
不过当我们点了后退按钮时,这些更新就丢失了。
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
Updates weren't lost before, what's happening?
|
Updates weren't lost before, what's happening?
|
||||||
|
@ -368,28 +374,42 @@ block get-heroes-details
|
||||||
from a server, if we want changes to persist, we'll need to write them back to
|
from a server, if we want changes to persist, we'll need to write them back to
|
||||||
the server.
|
the server.
|
||||||
|
|
||||||
|
以前是不会丢失更新的,现在是怎么回事?
|
||||||
|
当该应用使用mock出来的英雄列表时,修改的是一份全局共享的英雄列表,而现在改成了从服务器获取数据。
|
||||||
|
如果我们希望这些更改被持久化,我们就得把它们写回服务器。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### Save hero details
|
### Save hero details
|
||||||
|
|
||||||
|
### 保存英雄详情
|
||||||
|
|
||||||
Let's ensure that edits to a hero's name aren't lost. Start by adding,
|
Let's ensure that edits to a hero's name aren't lost. Start by adding,
|
||||||
to the end of the hero detail template, a save button with a `click` event
|
to the end of the hero detail template, a save button with a `click` event
|
||||||
binding that invokes a new component method named `save`:
|
binding that invokes a new component method named `save`:
|
||||||
|
|
||||||
|
我们先来确保对英雄名字的编辑不会丢失。先在英雄详情模板的底部添加一个“保存”按钮,它绑定了一个`click`事件,事件中调用组件中一个名叫`save`的新方法:
|
||||||
|
|
||||||
+makeExcerpt('app/hero-detail.component.html', 'save')
|
+makeExcerpt('app/hero-detail.component.html', 'save')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The `save` method persists hero name changes using the hero service
|
The `save` method persists hero name changes using the hero service
|
||||||
`update` method and then navigates back to the previous view:
|
`update` method and then navigates back to the previous view:
|
||||||
|
|
||||||
|
`save`方法使用hero服务的`update`方法来持久化对英雄名字的修改,然后导航回前一个页面:
|
||||||
|
|
||||||
+makeExcerpt('app/hero-detail.component.ts', 'save')
|
+makeExcerpt('app/hero-detail.component.ts', 'save')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### Hero service `update` method
|
### Hero service `update` method
|
||||||
|
|
||||||
|
### hero服务的`update`方法
|
||||||
|
|
||||||
The overall structure of the `update` method is similar to that of
|
The overall structure of the `update` method is similar to that of
|
||||||
`getHeroes`, although we'll use an HTTP _put_ to persist changes
|
`getHeroes`, although we'll use an HTTP _put_ to persist changes
|
||||||
server-side:
|
server-side:
|
||||||
|
|
||||||
|
`update`方法的大致结构与`getHeroes`类似,不过我们使用HTTP的*put*方法来把修改持久化到服务端:
|
||||||
|
|
||||||
+makeExcerpt('app/hero.service.ts', 'update')
|
+makeExcerpt('app/hero.service.ts', 'update')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
|
@ -398,51 +418,80 @@ block get-heroes-details
|
||||||
calling `!{_JSON_stringify}`. We identify the body content type
|
calling `!{_JSON_stringify}`. We identify the body content type
|
||||||
(`application/json`) in the request header.
|
(`application/json`) in the request header.
|
||||||
|
|
||||||
|
我们通过一个编码在URL中的英雄id来告诉服务器应该更新哪个英雄。put的body是该英雄的JSON字符串,它是通过调用`!{_JSON_stringify}`得到的。
|
||||||
|
并且在请求头中标记出的body的内容类型(`application/json`)。
|
||||||
|
|
||||||
Refresh the browser and give it a try. Changes to hero names should now persist.
|
Refresh the browser and give it a try. Changes to hero names should now persist.
|
||||||
|
|
||||||
|
刷新浏览器试一下,对英雄名字的修改确实已经被持久化了。
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Add a hero
|
## Add a hero
|
||||||
|
|
||||||
|
## 添加英雄
|
||||||
|
|
||||||
To add a new hero we need to know the hero's name. Let's use an input
|
To add a new hero we need to know the hero's name. Let's use an input
|
||||||
element for that, paired with an add button.
|
element for that, paired with an add button.
|
||||||
|
|
||||||
|
要添加一个新的英雄,我们得先知道英雄的名字。我们使用一个input元素和一个“add”按钮来拿到它。
|
||||||
|
|
||||||
Insert the following into the heroes component HTML, first thing after
|
Insert the following into the heroes component HTML, first thing after
|
||||||
the heading:
|
the heading:
|
||||||
|
|
||||||
|
把下列代码插入heroes组件的HTML中,放在紧挨着头部的地方:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.html', 'add')
|
+makeExcerpt('app/heroes.component.html', 'add')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
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')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
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服务来创建一个具有此名字的英雄,并把这个新的英雄添加到我们的数组中。
|
||||||
|
|
||||||
Finally, we implement the `create` method in the `HeroService` class.
|
Finally, we implement the `create` method in the `HeroService` class.
|
||||||
|
|
||||||
|
最后,我们在`HeroService`类中实现这个`create`方法。
|
||||||
|
|
||||||
+makeExcerpt('app/hero.service.ts', 'create')
|
+makeExcerpt('app/hero.service.ts', 'create')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Refresh the browser and create some new heroes!
|
Refresh the browser and create some new heroes!
|
||||||
|
|
||||||
|
刷新浏览器,并创建一些新的英雄!
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Delete a hero
|
## Delete a hero
|
||||||
|
|
||||||
|
## 删除一个英雄
|
||||||
|
|
||||||
Too many heroes?
|
Too many heroes?
|
||||||
Let's add a delete button to each hero in the heroes view.
|
Let's add a delete button to each hero in the heroes view.
|
||||||
|
|
||||||
|
英雄太多了?
|
||||||
|
我们在英雄列表视图中来为每个英雄添加一个删除按钮吧。
|
||||||
|
|
||||||
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>`标签中的英雄名紧后边:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.html', 'delete', '')
|
+makeExcerpt('app/heroes.component.html', 'delete', '')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
The `<li>` element should now look like this:
|
The `<li>` element should now look like this:
|
||||||
|
|
||||||
|
`<li>`元素应该变成了这样:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.html', 'li-element')
|
+makeExcerpt('app/heroes.component.html', 'li-element')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
|
@ -451,8 +500,12 @@ 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>`的事件处理器,否则它会选中我们要删除的这位英雄。
|
||||||
|
|
||||||
The logic of the `delete` handler is a bit trickier:
|
The logic of the `delete` handler is a bit trickier:
|
||||||
|
|
||||||
|
`delete`处理器的逻辑略复杂:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.ts', 'delete')
|
+makeExcerpt('app/heroes.component.ts', 'delete')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
|
@ -460,22 +513,33 @@ 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服务,不过该组件仍然正确的更新了显示:它从数组中移除了被删除的英雄,如果删除的是正选中的英雄,还会清空选择。
|
||||||
|
|
||||||
: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.
|
||||||
This extra CSS accomplishes that:
|
This extra CSS accomplishes that:
|
||||||
|
|
||||||
|
我们希望删除按钮被放在英雄条目的最右边。
|
||||||
|
于是CSS变成了这样:
|
||||||
|
|
||||||
+makeExcerpt('app/heroes.component.css', 'additions')
|
+makeExcerpt('app/heroes.component.css', 'additions')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
### Hero service `delete` method
|
### Hero service `delete` method
|
||||||
|
|
||||||
|
### hero服务的`delete`方法
|
||||||
|
|
||||||
The hero service's `delete` method uses the _delete_ HTTP method to remove the hero from the server:
|
The hero service's `delete` method uses the _delete_ HTTP method to remove the hero from the server:
|
||||||
|
|
||||||
|
hero服务的`delete`方法使用HTTP的*delete*方法来从服务器上移除该英雄:
|
||||||
|
|
||||||
+makeExcerpt('app/hero.service.ts', 'delete')
|
+makeExcerpt('app/hero.service.ts', 'delete')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Refresh the browser and try the new delete functionality.
|
Refresh the browser and try the new delete functionality.
|
||||||
|
|
||||||
|
刷新浏览器,并试一下这个新的删除功能。
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
## !{_Observable}s
|
## !{_Observable}s
|
||||||
|
|
||||||
|
@ -485,7 +549,7 @@ block observables-section-intro
|
||||||
:marked
|
:marked
|
||||||
Each `Http` service method returns an `Observable` of HTTP `Response` objects.
|
Each `Http` service method returns an `Observable` of HTTP `Response` objects.
|
||||||
|
|
||||||
`Http`服务中的每个方法都返回一个Http `Response`对象的`Observable`实例。
|
`Http`服务中的每个方法都返回一个HTTP `Response`对象的`Observable`实例。
|
||||||
|
|
||||||
Our `HeroService` converts that `Observable` into a `Promise` and returns the promise to the caller.
|
Our `HeroService` converts that `Observable` into a `Promise` and returns the promise to the caller.
|
||||||
In this section we learn to return the `Observable` directly and discuss when and why that might be
|
In this section we learn to return the `Observable` directly and discuss when and why that might be
|
||||||
|
@ -520,7 +584,7 @@ block observables-section-intro
|
||||||
A single result in the form of a promise is easy for the calling component to consume
|
A single result in the form of a promise is easy for the calling component to consume
|
||||||
and it helps that promises are widely understood by JavaScript programmers.
|
and it helps that promises are widely understood by JavaScript programmers.
|
||||||
|
|
||||||
转换成承诺通常是更好地选择,我们通常要求`http`获取单块数据。只要接收到数据,就算完成。
|
转换成承诺通常是更好地选择,我们通常会要求`http.get`获取单块数据。只要接收到数据,就算完成。
|
||||||
使用承诺这种形式的结果是让调用方更容易写,并且承诺已经在JavaScript程序员中被广泛接受了。
|
使用承诺这种形式的结果是让调用方更容易写,并且承诺已经在JavaScript程序员中被广泛接受了。
|
||||||
:marked
|
:marked
|
||||||
But requests aren't always "one and done". We may start one request,
|
But requests aren't always "one and done". We may start one request,
|
||||||
|
@ -698,7 +762,7 @@ 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
|
||||||
|
@ -741,7 +805,7 @@ block observable-transformers
|
||||||
:marked
|
:marked
|
||||||
We load them all at once by importing `rxjs-extensions` at the top of `AppModule`.
|
We load them all at once by importing `rxjs-extensions` at the top of `AppModule`.
|
||||||
|
|
||||||
我们在`AppModule`中导入`rxjs-extensions`就可以一次性加载它们。
|
我们在顶级的`AppModule`中导入`rxjs-extensions`就可以一次性加载它们。
|
||||||
|
|
||||||
+makeExcerpt('app/app.module.ts', 'rxjs-extensions')(format='.')
|
+makeExcerpt('app/app.module.ts', 'rxjs-extensions')(format='.')
|
||||||
|
|
||||||
|
@ -763,7 +827,7 @@ block observable-transformers
|
||||||
<span ngio-ex>hero-search.component.ts</span>
|
<span ngio-ex>hero-search.component.ts</span>
|
||||||
and add it to the `!{_declarations}` !{_array}:
|
and add it to the `!{_declarations}` !{_array}:
|
||||||
|
|
||||||
最后,从`'./hero-search.component.ts'` 导入`HeroSearchComponent`并将其添加到`declarations`数组中。
|
最后,从<span ngio-ex>hero-search.component.ts</span>中导入`HeroSearchComponent`并将其添加到`declarations`数组中。
|
||||||
|
|
||||||
+makeExcerpt(declFile, 'search')
|
+makeExcerpt(declFile, 'search')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue