docs: 查漏补缺
This commit is contained in:
parent
013b34e36c
commit
5654533190
|
@ -542,7 +542,7 @@ AngularJS 为模板提供了七十多个内置指令。
|
|||
For more information on routing, see [Defining a basic route](guide/router#basic-route)
|
||||
in the [Routing & Navigation](guide/router) page.
|
||||
|
||||
要了解关于路由的更多信息,请参见[路由与导航](guide/router)的[RouterLink 绑定](guide/router#router-link)部分。
|
||||
要了解关于路由的更多信息,请参见[路由与导航](guide/router)的[定义基础路由](guide/router#basic-route)部分。
|
||||
|
||||
</td>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ This guide explains how to specify metadata and apply available compiler options
|
|||
|
||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">Watch Alex Rickabaugh explain the Angular compiler</a> at AngularConnect 2019.
|
||||
|
||||
观看编译器作者 Tobias Bosch 在 AngularConnect 2016 大会里,对<a href="http://v.youku.com/v_show/id_XMTc1NTE4NTkwOA==.html?from=y1.7-1.4" target="_blank">Angular 编译器</a>的演讲。
|
||||
<a href="https://www.youtube.com/watch?v=anphffaCZrQ">观看 Alex Rickabaugh 在 AngularConnect 2019 解释 Angular 编译器的演讲</a> .
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
A *component* controls a patch of screen called a [*view*](guide/glossary#view "Definition of view").
|
||||
For example, individual components define and control each of the following views from the [Tour of Heroes tutorial](tutorial):
|
||||
|
||||
*组件*控制屏幕上被称为*视图*的一小片区域。比如,[教程](tutorial/index)中的下列视图都是由一个个组件所定义和控制的:
|
||||
*组件*控制屏幕上被称为[*视图*](guide/glossary#view "Definition of view")的一小片区域。比如,[教程](tutorial/index)中的下列视图都是由一个个组件所定义和控制的:
|
||||
|
||||
* The app root with the navigation links.
|
||||
|
||||
|
|
|
@ -845,9 +845,12 @@ The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript for
|
|||
<code-example path="dependency-injection-in-action/src/app/minimal-logger.service.ts" region="minimal-logger-transpiled" header="dependency-injection-in-action/src/app/minimal-logger.service.ts"></code-example>
|
||||
|
||||
Notice that it doesn't have any members. It never grows no matter how many members you add to the class,
|
||||
as long as those members are typed but not implemented. Look again at the TypeScript `MinimalLogger` class to confirm that it has no implementation.
|
||||
as long as those members are typed but not implemented.
|
||||
|
||||
注意,***只要不实现它***,不管添加多少成员,它都不会增长大小,因为这些成员虽然是有类型的,但却没有实现。
|
||||
|
||||
Look again at the TypeScript `MinimalLogger` class to confirm that it has no implementation.
|
||||
|
||||
你可以再看看 TypeScript 的 `MinimalLogger` 类,确定一下它是没有实现的。
|
||||
|
||||
</div>
|
||||
|
|
|
@ -607,17 +607,17 @@ export class MyModule {
|
|||
{@a ie-9-10}
|
||||
### IE 9 and 10 support
|
||||
|
||||
### IE 9 和 10 支持 IE 9
|
||||
### IE 9 和 10 支持
|
||||
|
||||
Support for IE 9 and 10 has been deprecated and will be removed in a future version.
|
||||
Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework.
|
||||
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors.
|
||||
|
||||
对 IE 9 和 10 的支持已被弃用,并将在以后的版本中删除。支持像这样过时的浏览器会增加 bundle 的大小,增加代码的复杂性和测试的负载,还需要花费大量的时间和精力来改进框架。例如,修复问题可能会更加困难,因为对于现代浏览器来说,直接修复可能会因为没有收到供应商的更新而破坏那些有怪癖的旧版本。
|
||||
对 IE 9 和 10 的支持已被弃用,并将在以后的版本中删除。支持像这样过时的浏览器会增加打包尺寸,增加代码的复杂性和测试的负担,还需要花费大量的时间和精力来改进框架。例如,修复问题可能会更加困难,因为对于现代浏览器那些直接的修复方式可能会破坏那些没有收到更新的怪异旧版本。
|
||||
|
||||
The final decision was made on three key points:
|
||||
|
||||
最终决定于三个关键点:
|
||||
它的最终决定取决于三点:
|
||||
|
||||
- **Vendor support**: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support.
|
||||
|
||||
|
@ -625,7 +625,7 @@ The final decision was made on three key points:
|
|||
|
||||
- **Usage statistics**: We looked at usage trends for IE 9 and 10 from various sources and all indicated that usage percentages were extremely small (fractions of 1%).
|
||||
|
||||
**用法统计** :我们从不同来源查看了 IE 9 和 10 的使用趋势,并且都表明使用率非常小(1%的分数)。
|
||||
**用法统计** :我们从不同来源查看了 IE 9 和 10 的使用趋势,并且都表明其使用率非常小(不足 1%)。
|
||||
|
||||
- **Feedback from partners**: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9 and 10 support.
|
||||
|
||||
|
@ -640,16 +640,16 @@ The final decision was made on three key points:
|
|||
The purpose of `WrappedValue` is to allow the same object instance to be treated as different for the purposes of change detection.
|
||||
It is commonly used with the `async` pipe in the case where the `Observable` produces the same instance of the value.
|
||||
|
||||
`WrappedValue` 的目的是让同一个对象实例被视为不同的对象,以便进行变更检测。在 `Observable` 生成相同值的实例的情况下,它常用于 `async` 管道。
|
||||
`WrappedValue` 的目的是让同一个对象实例被视为不同的对象,以便进行变更检测。比如当 `Observable` 生成相同实例的时候,它常用于 `async` 管道。
|
||||
|
||||
Given that this use case is relatively rare and special handling impacts application performance, we have deprecated it in v10.
|
||||
No replacement is planned for this deprecation.
|
||||
|
||||
鉴于此用例相对较少,并且特殊处理会影响应用性能,因此我们已在第 10 版中弃用它。这次弃用并未计划更换。
|
||||
鉴于此用例相对较少,并且特殊处理会影响应用性能,因此我们已在第 10 版中弃用它。这项弃用并没有提供替代方案。
|
||||
|
||||
If you rely on the behavior that the same object instance should cause change detection, you have two options:
|
||||
|
||||
如果依赖同一个对象实例引起变更检测的行为,你有两个选择:
|
||||
如果你要依赖同一个对象实例引起变更检测的行为,那么有两个选择:
|
||||
|
||||
- Clone the resulting value so that it has a new identity.
|
||||
|
||||
|
@ -657,46 +657,46 @@ If you rely on the behavior that the same object instance should cause change de
|
|||
|
||||
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
||||
|
||||
显式调用[`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges)来强制进行更新。
|
||||
显式调用 [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) 进行强制更新。
|
||||
|
||||
{@a removed}
|
||||
|
||||
## Removed APIs
|
||||
|
||||
## 删除了 API
|
||||
## 删除的 API
|
||||
|
||||
The following APIs have been removed starting with version 10.0.0\*:
|
||||
|
||||
从 Version 10.0.0 \*开始,已经删除了以下 API:
|
||||
从 10.0.0 版开始,已经删除了以下 API:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ------- | --- | ----------- | ----- |
|
||||
| 包裹 | API | 更换 | 笔记 |
|
||||
| 包 | API | 替代品 | 备注 |
|
||||
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||
| `@angular/core` | 使用 Angular 特性的未修改的基类 | 添加 Angular 装饰器 | 有关详情,请参阅[迁移指南](guide/migration-undecorated-classes) |
|
||||
| `@angular/core` | 使用 Angular 特性的不带装饰器的基类 | 添加 Angular 装饰器 | 详情参阅[迁移指南](guide/migration-undecorated-classes) |
|
||||
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||
| `@angular/core` | `ModuleWithProviders` 没有泛型 | `ModuleWithProviders` 用泛型的 | 有关详情,请参阅[迁移指南](guide/migration-module-with-providers) |
|
||||
| `@angular/core` | 不带泛型的 `ModuleWithProviders` | 带泛型的 `ModuleWithProviders` | 详情参阅[迁移指南](guide/migration-module-with-providers) |
|
||||
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](#style-sanitization) for more info |
|
||||
| `@angular/core` | 风格消毒 | 不需要任何动作 | 有关更多信息,请参阅[样式清理 API 删除](#style-sanitization) |
|
||||
| `@angular/core` | 样式的无害化处理 | 不需要任何动作 | 详情参阅[移除了 样式无害化 API](#style-sanitization) |
|
||||
|
||||
\*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
|
||||
\*要查看版本 9 中移除的 API,请查看[版本 9 docs 站点](https://v9.angular.io/guide/deprecations#removed)上的本指南。
|
||||
\*要查看版本 9 中移除的 API,请查看[版本 9 文档站](https://v9.angular.io/guide/deprecations#removed)上本指南。
|
||||
|
||||
{@a esm5-fesm5}
|
||||
|
||||
### `esm5` and `fesm5` code formats in @angular/* npm packages
|
||||
|
||||
### @angular/* npm 软件包中的 `esm5` 和 `fesm5` 代码格式
|
||||
### `@angular/*` npm 软件包中的 `esm5` 和 `fesm5` 代码格式
|
||||
|
||||
As of Angular v8, the CLI primarily consumes the `fesm2015` variant of the code distributed via `@angular/*` npm packages.
|
||||
This renders the `esm5` and `fesm5` distributions obsolete and unnecessary, adding bloat to the package size and slowing down npm installations.
|
||||
|
||||
从 Angular v8 开始,CLI 就主要使用 通过 `@angular/*` 系列 npm 包分发的 `fesm2015` 变体代码。这就让 `esm5` 和 `fesm5` 的发行版变得过时和不必要,只会增加软件包大小并拖累了 npm 的安装速度。
|
||||
从 Angular v8 开始,CLI 就主要使用通过 `@angular/*` 系列 npm 包分发的 `fesm2015` 变体代码。这就让 `esm5` 和 `fesm5` 的发行版变得过时和不必要,只会增加软件包大小并拖累 npm 的安装速度。
|
||||
|
||||
This removal has no impact on CLI users, unless they modified their build configuration to explicitly consume these code distributions.
|
||||
|
||||
移除它们不会对 CLI 用户产生任何影响,除非他们修改了自己的构建配置以显式使用这些代码发行版。
|
||||
移除它们不会对 CLI 用户产生任何影响,除非他们修改了自己的构建配置以显式使用代码的这些发行版。
|
||||
|
||||
Any application still relying on the `esm5` and `fesm5` as the input to its build system will need to ensure that the build pipeline is capable of accepting JavaScript code conforming to ECMAScript 2015 (ES2015) language specification.
|
||||
|
||||
|
@ -754,17 +754,17 @@ For more information about the npm package format, see the [Angular Package Form
|
|||
{@a ie-9-10}
|
||||
### IE 9 and 10 support
|
||||
|
||||
### 对 IE 9 和 10 的支持
|
||||
### IE 9 和 10 支持
|
||||
|
||||
Support for IE 9 and 10 has been deprecated and will be removed in a future version.
|
||||
Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework.
|
||||
For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors.
|
||||
|
||||
对 IE 9 和 10 的支持已被弃用,并将在以后的版本中删除。支持像这样过时的浏览器会增加 bundle 的大小,增加代码的复杂性和测试的负载,还需要花费大量的时间和精力来改进框架。例如,修复问题可能会更加困难,因为对于现代浏览器来说,直接修复可能会因为没有收到供应商的更新而破坏那些有怪癖的旧版本。
|
||||
对 IE 9 和 10 的支持已被弃用,并将在以后的版本中删除。支持像这样过时的浏览器会增加打包尺寸,增加代码的复杂性和测试的负担,还需要花费大量的时间和精力来改进框架。例如,修复问题可能会更加困难,因为对于现代浏览器那些直接的修复方式可能会破坏那些没有收到更新的怪异旧版本。
|
||||
|
||||
The final decision was made on three key points:
|
||||
|
||||
最终决定于三个关键点:
|
||||
它的最终决定取决于三点:
|
||||
|
||||
- **Vendor support**: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support.
|
||||
|
||||
|
@ -772,7 +772,7 @@ The final decision was made on three key points:
|
|||
|
||||
- **Usage statistics**: We looked at usage trends for IE 9 and 10 from various sources and all indicated that usage percentages were extremely small (fractions of 1%).
|
||||
|
||||
**用法统计** :我们从不同来源查看了 IE 9 和 10 的使用趋势,并且都表明使用率非常小(1%的分数)。
|
||||
**用法统计** :我们从不同来源查看了 IE 9 和 10 的使用趋势,并且都表明其使用率非常小(不足 1%)。
|
||||
|
||||
- **Feedback from partners**: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9 and 10 support.
|
||||
|
||||
|
@ -781,23 +781,25 @@ The final decision was made on three key points:
|
|||
{@a removed}
|
||||
## Removed APIs
|
||||
|
||||
## 已删除的 API
|
||||
## 删除的 API
|
||||
|
||||
The following APIs have been removed starting with version 10.0.0*:
|
||||
The following APIs have been removed starting with version 10.0.0\*:
|
||||
|
||||
从 9.0.0\*版开始,以下 API 已被删除:
|
||||
从 10.0.0 版开始,已经删除了以下 API:
|
||||
|
||||
| Package | API | Replacement | Notes |
|
||||
| ---------------- | -------------- | ----------- | ----- |
|
||||
| 包 | API | 替代品 | 备注 | |
|
||||
| ------- | --- | ----------- | ----- |
|
||||
| 包 | API | 替代品 | 备注 |
|
||||
| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info |
|
||||
| `@angular/core` | 用到 Angular 特性的不带装饰器的基类 | 添加 Angular 装饰器 | 欲知详情,参见[迁移指南](guide/migration-undecorated-classes) |
|
||||
| `@angular/core` | 使用 Angular 特性的不带装饰器的基类 | 添加 Angular 装饰器 | 详情参阅[迁移指南](guide/migration-undecorated-classes) |
|
||||
| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info |
|
||||
| `@angular/core` | 不带泛型的 `ModuleWithProviders` | 带泛型的 `ModuleWithProviders` | 欲知详情,参见 [迁移指南](guide/migration-module-with-providers) |
|
||||
| `@angular/core` | 不带泛型的 `ModuleWithProviders` | 带泛型的 `ModuleWithProviders` | 详情参阅[迁移指南](guide/migration-module-with-providers) |
|
||||
| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](#style-sanitization) for more info |
|
||||
| `@angular/core` | 样式的无害化处理 | 不需要任何动作 | 详情参阅[移除了 样式无害化 API](#style-sanitization) |
|
||||
|
||||
*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
\*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed).
|
||||
|
||||
要查看版本 8 中删除的 API,请查看[版本 8 文档站点](https://v8.angular.io/guide/deprecations#removed)上的本指南。
|
||||
\*要查看版本 9 中移除的 API,请查看[版本 9 文档站](https://v9.angular.io/guide/deprecations#removed)上本指南。
|
||||
|
||||
<!-- The following anchor is used by redirects from the removed API pages. Do not change or remove. -->
|
||||
{@a http}
|
||||
|
@ -880,9 +882,9 @@ For more information about using `@angular/common/http`, see the [HttpClient gui
|
|||
|
||||
### Style Sanitization for `[style]` and `[style.prop]` bindings
|
||||
|
||||
### `[style]` 和 `[style.prop]` 绑定的 Style `[style.prop]`
|
||||
### `[style]` 和 `[style.prop]` 绑定的样式无害化
|
||||
|
||||
Angular used to sanitize `[style]` and `[style.prop]` bindings to prevent malicious code from being inserted through `javascript:` expressions in CSS `url()` entries. However, most modern browsers no longer support the usage of these expressions, so sanitization was only maintained for the sake of IE 6 and 7. Given that Angular does not support either IE 6 or 7 and sanitization has a performance cost, we will no longer sanitize style bindings as of version 10 of Angular.
|
||||
|
||||
Angular 用来清理 `[style]` 和 `[style.prop]` 绑定,以防止恶意代码通过 CSS `url()` 条目中的 `javascript:` expressions 进行插入。但是,大多数现代浏览器都不再支持这些表达式的使用,所以只有 IE 6 和 7 才能维护清理。鉴于 Angular 不支持 IE 6 或 7,并且清理有性能代价,我们将不再清理 Angular 版本 10 中的样式绑定。
|
||||
Angular 会清理 `[style]` 和 `[style.prop]` 绑定,以防止恶意代码通过 CSS `url()` 条目中的 `javascript:` 表达式进行插入。但是,大多数现代浏览器都已不再支持这些表达式的使用,所以这种清理只对 IE 6 和 7 才有意义。鉴于 Angular 不支持 IE 6 或 7,并且这种清理有性能代价,因此我们将不再清理 Angular 版本 10 中的样式绑定。
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of t
|
|||
Read more about `ngFor` and `*` in the [ngFor section](guide/template-syntax#ngfor) of the [Template Syntax](guide/template-syntax) page.
|
||||
|
||||
不要忘记 `*ngFor` 中的前导星号 (\*)。它是语法中不可或缺的一部分。
|
||||
更多信息,见[模板语法](guide/template-syntax#ngFor)。
|
||||
关于 `ngFor` 和 `*` 的更多信息,参见[模板语法](guide/template-syntax#ngFor)页的 [ngFor 部分](guide/template-syntax#ngfor)。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -305,7 +305,7 @@ of hero names into an array of `Hero` objects. For that you'll need a `Hero` cla
|
|||
|
||||
This command creates the following code.
|
||||
|
||||
代码如下:
|
||||
此命令创建了如下代码:
|
||||
|
||||
<code-example path="displaying-data/src/app/hero.ts" header="src/app/hero.ts"></code-example>
|
||||
|
||||
|
@ -429,6 +429,7 @@ The browser should refresh automatically and the message should disappear.
|
|||
试一下。因为这个数组中有四个条目,所以消息应该显示出来。
|
||||
回到 `app.component.ts`,从英雄数组中删除或注释掉一个元素。
|
||||
浏览器应该自动刷新,消息应该会消失。
|
||||
|
||||
## Summary
|
||||
|
||||
## 小结
|
||||
|
|
|
@ -345,7 +345,7 @@ See also [Schematics CLI](#schematics-cli).
|
|||
|
||||
A class with the `@Component()` [decorator](#decorator) that associates it with a companion [template](#template). Together, the component class and template define a [view](#view).
|
||||
|
||||
一个带有 `@Component()` [装饰器](#decorator)的类,和它的伴生[模板](#template)关联在一起。组件及其模板共同定义了一个[视图](#view)。
|
||||
一个带有 `@Component()` [装饰器](#decorator)的类,和它的伴生[模板](#template)关联在一起。组件类及其模板共同定义了一个[视图](#view)。
|
||||
|
||||
A component is a special type of [directive](#directive).
|
||||
The `@Component()` decorator extends the `@Directive()` decorator with template-oriented features.
|
||||
|
@ -358,7 +358,7 @@ Angular 的组件类负责暴露数据,并通过[数据绑定机制](#data-bin
|
|||
|
||||
Read more about component classes, templates, and views in [Introduction to Angular concepts](guide/architecture).
|
||||
|
||||
要了解更多关于组件、模板和视图的知识,参见 [架构概览](guide/architecture) 一章。
|
||||
要了解更多关于组件类、模板和视图的知识,参见 [架构概览](guide/architecture) 一章。
|
||||
|
||||
## configuration
|
||||
|
||||
|
@ -682,14 +682,14 @@ Compare to [custom element](#custom-element).
|
|||
|
||||
## 入口点(Entry Point)
|
||||
|
||||
A JavaScript module(#module) that is intended to be imported by a user of [an
|
||||
A [JavaScript module](#module) that is intended to be imported by a user of [an
|
||||
npm package](guide/npm-packages). An entry-point module typically re-exports
|
||||
symbols from other internal modules. A package can contain multiple
|
||||
entry points. For example, the `@angular/core` package has two entry-point
|
||||
modules, which can be imported using the module names `@angular/core` and
|
||||
`@angular/core/testing`.
|
||||
|
||||
JavaScript 模块(#module)的目的是供 [npm 包](guide/npm-packages)的用户进行导入。入口点模块通常会重新导出来自其它内部模块的一些符号。每个包可以包含多个入口点。比如 `@angular/core` 就有两个入口点模块,它们可以使用名字 `@angular/core` 和 `@angular/core/testing` 进行导入。
|
||||
[JavaScript 模块](#module)的目的是供 [npm 包](guide/npm-packages)的用户进行导入。入口点模块通常会重新导出来自其它内部模块的一些符号。每个包可以包含多个入口点。比如 `@angular/core` 就有两个入口点模块,它们可以使用名字 `@angular/core` 和 `@angular/core/testing` 进行导入。
|
||||
|
||||
{@a F}
|
||||
|
||||
|
@ -826,10 +826,9 @@ or displayed between element tags, as in this example.
|
|||
[属性数据绑定 (property data binding)](#data-binding) 的一种形式,位于双大括号中的[模板表达式 (template expression)](#template-expression)会被渲染成文本。
|
||||
在被赋值给元素属性或者显示在元素标签中之前,这些文本可能会先与周边的文本合并,参见下面的例子。
|
||||
|
||||
<code-example language="html" escape="html">
|
||||
```html
|
||||
<label>My current hero is {{hero.name}}</label>
|
||||
|
||||
</code-example>
|
||||
```
|
||||
|
||||
Read more about [interpolation](guide/template-syntax#interpolation) in [Template Syntax](guide/template-syntax).
|
||||
|
||||
|
@ -1501,7 +1500,7 @@ You can also define a custom builder, and add a target to the project configurat
|
|||
|
||||
Code that defines how to render a component's [view](#view).
|
||||
|
||||
模板是与组件相关的代码,用来定义如何在 HTML 中渲染组件的[视图](#view)。
|
||||
用来定义要如何在 HTML 中渲染组件[视图](#view)的代码。
|
||||
|
||||
A template combines straight HTML with Angular [data-binding](#data-binding) syntax, [directives](#directive),
|
||||
and [template expressions](#template-expression) (logical constructs).
|
||||
|
@ -1511,7 +1510,7 @@ The Angular elements insert or calculate values that modify the HTML elements be
|
|||
|
||||
A template is associated with a [component class](#component) through the `@Component()` [decorator](#decorator). The template code can be provided inline, as the value of the `template` property, or in a separate HTML file linked through the `templateUrl` property.
|
||||
|
||||
模板通过 `@Component()` [装饰器](#decorator)与[组件](#component)类关联起来。其 HTML 可以作为 `template` 属性的值用内联的方式提供,也可以通过 `templateUrl` 属性链接到一个独立的 HTML 文件。
|
||||
模板通过 `@Component()` [装饰器](#decorator)与[组件类](#component)类关联起来。模板代码可以作为 `template` 属性的值用内联的方式提供,也可以通过 `templateUrl` 属性链接到一个独立的 HTML 文件。
|
||||
|
||||
Additional templates, represented by `TemplateRef` objects, can define alternative or *embedded* views, which can be referenced from multiple components.
|
||||
|
||||
|
@ -1654,7 +1653,7 @@ Views are typically collected into [view hierarchies](#view-tree).
|
|||
|
||||
[组件 (component)](#component) 类及其关联的[模板 (template)](#template)定义了一个视图。
|
||||
具体实现上,视图由一个与该组件相关的 `ViewRef` 实例表示。
|
||||
属于某个组件的视图叫做*宿主视图*。
|
||||
直属于某个组件的视图叫做*宿主视图*。
|
||||
通常会把视图组织成一些[视图树(view hierarchies)](#view-tree)。
|
||||
|
||||
Properties of elements in a view can change dynamically, in response to user actions;
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
# Ivy compatibility examples
|
||||
|
||||
# Ivy 的兼容性例子
|
||||
|
||||
This appendix is intended to provide more background on Ivy changes. Many of these examples list error messages you may see, so searching by error message might be a good idea if you are debugging.
|
||||
|
||||
本附录旨在为 Ivy 的变更提供更多背景信息。其中很多例子列出了你可能会看到的错误信息,所以如果你正在调试,按错误信息搜索可能是个好主意。
|
||||
|
||||
<div class="alert is-critical">
|
||||
NOTE: Most of these issues affect a small percentage of applications encountering unusual or rare edge cases.
|
||||
</div>
|
||||
|
||||
{@a content-children-descendants}
|
||||
|
||||
## @ContentChildren queries only match direct children by default
|
||||
|
||||
## @ContentChildren 查询默认只匹配直接子组件
|
||||
|
||||
### Basic example of change
|
||||
|
||||
### 变更的基本例子
|
||||
|
||||
Let's say a component (`Comp`) has a `@ContentChildren` query for `'foo'`:
|
||||
|
||||
假设某个组件( `Comp` )对 `'foo'` 有 `@ContentChildren` 查询:
|
||||
|
||||
```html
|
||||
<comp>
|
||||
<div>
|
||||
|
@ -24,17 +35,27 @@ Let's say a component (`Comp`) has a `@ContentChildren` query for `'foo'`:
|
|||
In the previous runtime, the `<div>` with `#foo` would match.
|
||||
With Ivy, that `<div>` does not match because it is not a direct child of `<comp>`.
|
||||
|
||||
在之前的运行时中,带 `#foo` 的 `<div>` 会匹配到。而在 Ivy 中, `<div>` 不能匹配,因为它不是 `<comp>` 的直接子节点。
|
||||
|
||||
### Background
|
||||
|
||||
### 背景
|
||||
|
||||
By default, `@ContentChildren` queries have the `descendants` flag set to `false`.
|
||||
|
||||
默认情况下, `@ContentChildren` 查询的 `descendants` 标志设置为 `false` 。
|
||||
|
||||
In the previous rendering engine, "descendants" referred to "descendant directives".
|
||||
An element could be a match as long as there were no other directives between the element and the requesting directive.
|
||||
This made sense for directives with nesting like tabs, where nested tab directives might not be desirable to match.
|
||||
However, this caused surprising behavior for users because adding an unrelated directive like `ngClass` to a wrapper element could invalidate query results.
|
||||
|
||||
在前面的渲染引擎中,“descendants” 指的是“后代指令”。只要元素和请求指令之间没有其它指令,元素就可以匹配。这对于类似于 tabs (页标签组)的嵌套的指令是有意义的,其中嵌套的 tab 指令可能不适合匹配。但是,这会给用户带来令人惊讶的行为,因为只要在包装器元素中添加一个不相关的指令(如 `ngClass`) 就可能会让查询结果无效。
|
||||
|
||||
For example, with the content query and template below, the last two `Tab` directives would not be matches:
|
||||
|
||||
例如,如果使用下面的内容查询和模板,最后两个 `Tab` 指令不匹配:
|
||||
|
||||
```
|
||||
@ContentChildren(Tab, {descendants: false}) tabs: QueryList<Tab>
|
||||
```
|
||||
|
@ -56,6 +77,8 @@ For example, with the content query and template below, the last two `Tab` direc
|
|||
In addition, the differences between type and string predicates were subtle and sometimes unclear.
|
||||
For example, if you replace the type predicate above with a `'foo'` string predicate, the matches change:
|
||||
|
||||
另外,使用类型谓词和使用字符串谓词之间的差异很微妙,有时甚至都分不清。例如,如果用 `'foo'` 字符串谓词替换上面的类型谓词,匹配就会改变:
|
||||
|
||||
```
|
||||
@ContentChildren('foo', {descendants: false}) foos: QueryList<ElementRef>
|
||||
```
|
||||
|
@ -79,7 +102,12 @@ Instead, we simplified the mental model so that "descendants" refers to DOM nest
|
|||
Any DOM element between the requesting component and a potential match will invalidate that match.
|
||||
Type predicates and string predicates also have identical matching behavior.
|
||||
|
||||
由于之前的行为对用户来说是不一致和令人惊讶的,所以我们不打算在 Ivy 中重现它。相反,我们简化了其心智模型,以便 “descendants” 只标识 DOM 嵌套。位于发出请求的组件和潜在匹配项之间的任何 DOM 元素都会使该匹配失效。类型谓词和字符串谓词也有了相同的匹配行为。
|
||||
|
||||
Ivy behavior for directive/string predicates:
|
||||
|
||||
指令/字符串谓词的 Ivy 行为:
|
||||
|
||||
```
|
||||
<tab-list>
|
||||
<div>
|
||||
|
@ -96,27 +124,45 @@ Ivy behavior for directive/string predicates:
|
|||
|
||||
### Example of error
|
||||
|
||||
### 错误信息的例子
|
||||
|
||||
The error message that you see will depend on how the particular content query is used in the application code.
|
||||
Frequently, an error is thrown when a property is referenced on the content query result (which is now `undefined`).
|
||||
|
||||
你看到的错误信息取决于应用代码中特定的内容查询的使用方式。当在内容查询结果中引用一个属性(这里是 `undefined`)时,就会抛出一个错误。
|
||||
|
||||
For example, if the component sets the content query results to a property, `foos`, `foos.first.bar` would throw the error:
|
||||
|
||||
例如,如果组件把内容查询结果设置为属性,那么 `foos`、`foos.first.bar` 会抛出错误:
|
||||
|
||||
```
|
||||
Uncaught TypeError: Cannot read property 'bar' of undefined
|
||||
```
|
||||
|
||||
If you see an error like this, and the `undefined` property refers to the result of a `@ContentChildren` query, it may well be caused by this change.
|
||||
|
||||
如果你看到这样的错误,并且 `undefined` 属性引用了 `@ContentChildren` 查询的结果,那么很可能就是由于这个变化造成的。
|
||||
|
||||
### Recommended fix
|
||||
|
||||
### 推荐的修复方式
|
||||
|
||||
You can either add the `descendants: true` flag to ignore wrapper elements or remove the wrapper elements themselves.
|
||||
|
||||
你可以添加 `descendants: true` 标志来忽略包装元素,也可以自己删除包装元素。
|
||||
|
||||
Option 1:
|
||||
|
||||
方案 1:
|
||||
|
||||
```
|
||||
@ContentChildren('foo', {descendants: true}) foos: QueryList<ElementRef>;
|
||||
```
|
||||
|
||||
Option 2:
|
||||
|
||||
方案 2:
|
||||
|
||||
```
|
||||
<comp>
|
||||
<div #foo></div> <!-- matches in both old runtime and new runtime -->
|
||||
|
@ -124,12 +170,19 @@ Option 2:
|
|||
```
|
||||
|
||||
{@a undecorated-classes}
|
||||
|
||||
## All classes that use Angular DI must have an Angular class-level decorator
|
||||
|
||||
## 所有使用 Angular DI 的类都必须有一个 Angular 类级装饰器
|
||||
|
||||
### Basic example of change:
|
||||
|
||||
### 变更的基本例子:
|
||||
|
||||
In the previous rendering engine, the following would work:
|
||||
|
||||
在以前的渲染引擎中,下列代码可以正常工作:
|
||||
|
||||
```
|
||||
export class DataService {
|
||||
constructor(@Inject('CONFIG') public config: DataConfig) {}
|
||||
|
@ -141,8 +194,12 @@ export class AppService extends DataService {...}
|
|||
|
||||
In Ivy, it will throw an error because `DataService` is using Angular dependency injection, but is missing an `@Injectable` decorator.
|
||||
|
||||
在 Ivy 中,它会抛出一个错误,因为 `DataService` 正在使用 Angular 依赖注入,但它却缺少一个 `@Injectable` 装饰器。
|
||||
|
||||
The following would also work in the previous rendering engine, but in Ivy would require a `@Directive` decorator because it uses DI:
|
||||
|
||||
下列渲染引擎也能正常工作,但是 Ivy 需要一个 `@Directive` 装饰器,因为它使用了 DI:
|
||||
|
||||
```
|
||||
export class BaseMenu {
|
||||
constructor(private vcr: ViewContainerRef) {}
|
||||
|
@ -154,25 +211,41 @@ export class SettingsMenu extends BaseMenu {}
|
|||
|
||||
The same is true if your directive class extends a decorated directive, but does not have a decorator of its own.
|
||||
|
||||
如果指令类扩展了装饰指令,但却没有自己的装饰器,那也是如此。
|
||||
|
||||
If you're using the CLI, there are two automated migrations that should transition your code for you ([this one](guide/migration-injectable) and [this one](guide/migration-undecorated-classes)).
|
||||
However, as you're adding new code in version 9, you may run into this difference.
|
||||
|
||||
如果你正在使用 CLI,那么有两个自动迁移应该为你转移你的代码( [本章](guide/migration-injectable)和[本章](guide/migration-undecorated-classes) )。但是,当你在版本 9 中添加新代码时,可能会遇到这种不同。
|
||||
|
||||
### Background
|
||||
|
||||
### 背景
|
||||
|
||||
When a class has an Angular decorator like `@Injectable` or `@Directive`, the Angular compiler generates extra code to support injecting dependencies into the constructor of your class.
|
||||
When using inheritance, Ivy needs both the parent class and the child class to apply a decorator to generate the correct code.
|
||||
Otherwise, when the decorator is missing from the parent class, the subclass will inherit a constructor from a class for which the compiler did not generate special constructor info, and Angular won't have the dependency info it needs to create it properly.
|
||||
|
||||
当一个类有一个像 `@Injectable` 或 `@Directive` 这样的 Angular 装饰器时,Angular 编译器会生成额外的代码,以支持把依赖注入到类的构造函数中。当使用继承时,Ivy 既需要父类,也要让子类应用装饰器来生成正确的代码。否则,当父类中缺少装饰器时,该子类将继承一个构造函数,而这个构造函数并没有为编译器生成特殊的构造函数信息,而 Angular 也没有正确创建它所需的依赖信息。
|
||||
|
||||
In the previous rendering engine, the compiler had global knowledge, so in some cases (such as AOT mode or the presence of certain injection flags), it could look up the missing data.
|
||||
However, the Ivy compiler only processes each class in isolation.
|
||||
This means that compilation has the potential to be faster (and opens the framework up for optimizations and features going forward), but the compiler can't automatically infer the same information as before.
|
||||
|
||||
在之前的渲染引擎中,编译器具有全局知识,所以在某些情况下(比如 AOT 模式或某些注入标志的存在),它可以查找丢失的数据。然而,Ivy 编译器只是孤立地处理每个类。这意味着编译有可能更快(并为今后的优化和特性打开框架),但编译器不能自动推断出和以前一样的信息。
|
||||
|
||||
Adding the proper decorator explicitly provides this information.
|
||||
|
||||
添加合适的装饰器会明确提供这些信息。
|
||||
|
||||
### Example of error
|
||||
|
||||
### 错误信息的例子
|
||||
|
||||
In JIT mode, the framework will throw the following error:
|
||||
|
||||
在 JIT 模式下,该框架会抛出以下错误:
|
||||
|
||||
```
|
||||
ERROR: This constructor is not compatible with Angular Dependency Injection because its dependency at index X of the parameter list is invalid.
|
||||
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
|
||||
|
@ -182,6 +255,8 @@ Please check that 1) the type for the parameter at index X is correct and 2) the
|
|||
|
||||
In AOT mode, you'll see something like:
|
||||
|
||||
在 AOT 模式下,你会看到如下内容:
|
||||
|
||||
```
|
||||
X inherits its constructor from Y, but the latter does not have an Angular decorator of its own.
|
||||
Dependency injection will not be able to resolve the parameters of Y's constructor. Either add a
|
||||
|
@ -192,16 +267,24 @@ In some cases, the framework may not be able to detect the missing decorator.
|
|||
In these cases, you'll generally see a runtime error thrown when there is a property access attempted on the missing dependency.
|
||||
If dependency was `foo`, you'd see an error when accessing something like `foo.bar`:
|
||||
|
||||
在某些情况下,框架可能无法检测到丢失的装饰器。在这种情况下,你会发现试图对所缺的依赖项进行属性访问时,就会抛出一个运行时错误。如果依赖是 `foo` ,你在访问 `foo.bar` 这样的东西时会看到一个错误:
|
||||
|
||||
```
|
||||
Uncaught TypeError: Cannot read property 'bar' of undefined
|
||||
```
|
||||
|
||||
If you see an error like this, and the `undefined` value refers to something that should have been injected, it may be this change.
|
||||
|
||||
如果你看到这样的错误,并且 `undefined` 值引用了应该注入的内容,那么可能就是这种变化。
|
||||
|
||||
### Recommended fix
|
||||
|
||||
### 推荐的修复方式
|
||||
|
||||
- Add an `@Injectable` decorator to anything you plan to provide or inject.
|
||||
|
||||
把 `@Injectable` 装饰器添加到你打算提供或注入的东西中。
|
||||
|
||||
```
|
||||
@Injectable()
|
||||
export class DataService {
|
||||
|
@ -214,6 +297,8 @@ export class AppService extends DataService {...}
|
|||
|
||||
- Add a [selectorless `@Directive` decorator](guide/migration-undecorated-classes#what-does-it-mean-to-have-a-directive-decorator-with-no-metadata-inside-of-it) to any class that extends a directive or any class from which a directive inherits.
|
||||
|
||||
把 [无选择器的 `@Directive` 装饰器](guide/migration-undecorated-classes#what-does-it-mean-to-have-a-directive-decorator-with-no-metadata-inside-of-it)添加到扩展指令的类或被指令继承的任何类中。
|
||||
|
||||
```
|
||||
@Directive() // selectorless, so it's not usable directly
|
||||
export class BaseMenu {
|
||||
|
@ -225,10 +310,15 @@ export class SettingsMenu extends BaseMenu {}
|
|||
```
|
||||
|
||||
{@a select-value-binding}
|
||||
|
||||
## Cannot Bind to `value` property of `<select>` with `*ngFor`
|
||||
|
||||
## 无法使用 `*ngFor` 绑定到 `<select>` 的 `value` 属性
|
||||
|
||||
### Basic example of change
|
||||
|
||||
### 变更的基本例子
|
||||
|
||||
```html
|
||||
<select [value]="someValue">
|
||||
<option *ngFor="let option of options" [value]="option"> {{ option }} <option>
|
||||
|
@ -238,11 +328,17 @@ export class SettingsMenu extends BaseMenu {}
|
|||
In the View Engine runtime, the above code would set the initial value of the `<select>` as expected.
|
||||
In Ivy, the initial value would not be set at all in this case.
|
||||
|
||||
在 View Engine 的运行时,上面的代码会按照预期的那样设置 `<select>` 的初始值。在 Ivy 中,在这种情况下根本不会设置初始值。
|
||||
|
||||
### Background
|
||||
|
||||
### 背景
|
||||
|
||||
Prior to Ivy, directive input bindings were always executed in their own change detection pass before any DOM bindings were processed.
|
||||
This was an implementation detail that supported the use case in question:
|
||||
|
||||
在 Ivy 之前,指令输入绑定总是在处理任何 DOM 绑定之前,先在自己的变更检测过程中执行。下面是一个支持这个用例的实现细节:
|
||||
|
||||
```html
|
||||
<select [value]="someValue">
|
||||
<option *ngFor="let option of options" [value]="option"> {{ option }} <option>
|
||||
|
@ -253,21 +349,38 @@ It happened to work because the `*ngFor` would be checked first, during the dire
|
|||
Then the DOM binding pass would run, which would check the `value` binding.
|
||||
At this time, it would be able to match the value against one of the existing options, and set the value of the `<select>` element in the DOM to display that option.
|
||||
|
||||
它可以工作,因为在指令输入绑定过程中会先检查 `*ngFor`,从而先创建选项。然后运行一轮 DOM 绑定,它会检查 `value` 绑定。这时,它可以把这个值与其中一个现有选项进行匹配,并在 DOM 中设置 `<select>` 元素的值,以显示该选项。
|
||||
|
||||
In Ivy, bindings are checked in the order they are defined in the template, regardless of whether they are directive input bindings or DOM bindings.
|
||||
This change makes change detection easier to reason about for debugging purposes, since bindings will be checked in depth-first order as declared in the template.
|
||||
|
||||
在 Ivy 中,绑定会按模板中定义的顺序进行检查,不论它们是指令的输入绑定还是 DOM 绑定。这种变化使得变更检测更容易被调试,因为绑定会按照模板中声明的顺序进行深度优先的检查。
|
||||
|
||||
In this case, it means that the `value` binding will be checked before the `*ngFor` is checked, as it is declared above the `*ngFor` in the template.
|
||||
Consequently, the value of the `<select>` element will be set before any options are created, and it won't be able to match and display the correct option in the DOM.
|
||||
|
||||
在这种情况下,这意味着在检查 `*ngFor` 之前,会先检查 `value` 绑定,因为它是在模板的 `*ngFor` 上面声明的。因此,`<select>` 元素的值会在创建任何选项之前设置,并且无法在 DOM 中匹配并显示正确的选项。
|
||||
|
||||
### Example of error
|
||||
|
||||
### 错误信息的例子
|
||||
|
||||
There is no error thrown, but the `<select>` in question will not have the correct initial value displayed in the DOM.
|
||||
|
||||
不会抛出任何错误,但是问题中的 `<select>` 没有在 DOM 中显示正确的初始值。
|
||||
|
||||
### Recommended fix
|
||||
|
||||
### 推荐的修复方式
|
||||
|
||||
To fix this problem, we recommend binding to the `selected` property on the `<option>` instead of the `value` on the `<select>`.
|
||||
|
||||
为了解决这个问题,我们建议绑定 `<option>` 上的 `selected` 属性,而不要绑定 `<select>` 上的 `value` 。
|
||||
|
||||
*Before*
|
||||
|
||||
*以前*
|
||||
|
||||
```html
|
||||
<select [value]="someValue">
|
||||
<option *ngFor="let option of options" [value]="option"> {{ option }} <option>
|
||||
|
@ -275,6 +388,9 @@ To fix this problem, we recommend binding to the `selected` property on the `<op
|
|||
```
|
||||
|
||||
*After*
|
||||
|
||||
*之后*
|
||||
|
||||
```html
|
||||
<select>
|
||||
<option *ngFor="let option of options" [value]="option" [selected]="someValue == option">
|
||||
|
@ -284,10 +400,15 @@ To fix this problem, we recommend binding to the `selected` property on the `<op
|
|||
```
|
||||
|
||||
{@a forward-refs-directive-inputs}
|
||||
|
||||
## Forward references to directive inputs accessed through local refs are no longer supported.
|
||||
|
||||
## 不再支持对通过本地引用访问的指令输入属性的前向引用。
|
||||
|
||||
### Basic example of change
|
||||
|
||||
### 变更的基本例子
|
||||
|
||||
```ts
|
||||
@Directive({
|
||||
selector: '[myDir]',
|
||||
|
@ -306,31 +427,53 @@ export class MyDir {
|
|||
In the View Engine runtime, the above code would print out the name without any errors.
|
||||
In Ivy, the `myDir.name` binding will throw an `ExpressionChangedAfterItHasBeenCheckedError`.
|
||||
|
||||
在 View Engine 的运行时,上面的代码会打印出这个名字而不会出现任何错误。在 Ivy 中, `myDir.name` 绑定会抛出一个 `ExpressionChangedAfterItHasBeenCheckedError` 。
|
||||
|
||||
### Background
|
||||
|
||||
### 背景
|
||||
|
||||
In the ViewEngine runtime, directive input bindings and element bindings were executed in different stages. Angular would process the template one full time to check directive inputs only (e.g. `[name]`), then process the whole template again to check element and text bindings only (e.g.`{{ myDir.name }}`). This meant that the `name` directive input would be checked before the `myDir.name` text binding despite their relative order in the template, which some users felt to be counterintuitive.
|
||||
|
||||
在 ViewEngine 的运行时里,指令输入绑定和元素绑定是在不同的阶段执行的。 Angular 会全局处理模板,先只检查指令的输入(比如 `[name]` ),然后再针对元素和文本的绑定(例如 `{{ myDir.name }}` )处理整个模板。这意味着在 `myDir.name` 文本绑定之前会检查 `name` 指令的输入,尽管它们在模板中有相对的顺序,但有些用户会觉得这样违反直觉。
|
||||
|
||||
In contrast, Ivy processes the template in just one pass, so that bindings are checked in the same order that they are written in the template. In this case, it means that the `myDir.name` binding will be checked before the `name` input sets the property on the directive (and thus it will be `undefined`). Since the `myDir.name` property will be set by the time the next change detection pass runs, a change detection error is thrown.
|
||||
|
||||
相比之下,Ivy 只会在一轮中对模板进行处理,因此会按照它们在模板中编写的顺序来检查绑定。在这种情况下,这意味着在输入属性 `name` 设置该指令的属性之前,会检查 `myDir.name` 绑定(因此它将是 `undefined`)。`myDir.name` 属性的值是在下一次变更检测过程的运行时设置的,所以会抛出一个变更检测错误。
|
||||
|
||||
### Example of error
|
||||
|
||||
### 错误信息的例子
|
||||
|
||||
Assuming that the value for `myName` is `Angular`, you should see an error that looks like
|
||||
|
||||
假设 `myName` 的值是 `Angular` ,你会看到一个类似这样的错误
|
||||
|
||||
```
|
||||
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Angular'.
|
||||
```
|
||||
|
||||
### Recommended fix
|
||||
|
||||
### 推荐的修复方式
|
||||
|
||||
To fix this problem, we recommend either getting the information for the binding directly from the host component (e.g. the `myName` property from our example) or to move the data binding after the directive has been declared so that the initial value is available on the first pass.
|
||||
|
||||
为了解决这个问题,我们建议你直接从宿主组件中获取绑定的信息(比如我们这个例子中的 `myName` 属性),或者把数据绑定移到指令声明之后,以便初始值在第一轮中就是可用的。
|
||||
|
||||
*Before*
|
||||
|
||||
*以前*
|
||||
|
||||
```html
|
||||
{{ myDir.name }}
|
||||
<div myDir #myDir="myDir" [name]="myName"></div>
|
||||
```
|
||||
|
||||
*After*
|
||||
|
||||
*之后*
|
||||
|
||||
```html
|
||||
{{ myName }}
|
||||
<div myDir [name]="myName"></div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Providing dependencies in modules
|
||||
|
||||
# 服务提供者
|
||||
# 在模块中提供依赖
|
||||
|
||||
A provider is an instruction to the [Dependency Injection](/guide/dependency-injection) system on how to obtain a value for a dependency. Most of the time, these dependencies are services that you create and provide.
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ Reactive forms provide access to information about a given control through prope
|
|||
These properties and methods of the underlying [AbstractControl](api/forms/AbstractControl "API reference.") class are used to control form state and determine when to display messages when handling [input validation](#basic-form-validation "Learn more about validating form input.").
|
||||
|
||||
响应式表单还能通过每个实例的属性和方法提供关于特定控件的更多信息。[AbstractControl](api/forms/AbstractControl) 的这些属性和方法用于控制表单状态,并在处理表单校验时决定何时显示信息。
|
||||
欲知详情,参见稍后的[简单表单验证](#basic-form-validation)一节。
|
||||
欲知详情,参见稍后的[输入验证](#basic-form-validation)一节。
|
||||
|
||||
Read about other `FormControl` properties and methods in the [API Reference](api/forms/FormControl "Detailed syntax reference.").
|
||||
|
||||
|
|
|
@ -133,11 +133,11 @@ In general, you can expect the following release cycle:
|
|||
|
||||
* A patch release and pre-release (`next` or `rc`) build almost every week
|
||||
|
||||
差不多每周一个补丁版本
|
||||
差不多每周一个发行版或预发行版(`next` 或 `rc`)的补丁版本
|
||||
|
||||
This cadence of releases gives eager developers access to new features as soon as they are fully developed and pass through our code review and integration testing processes, while maintaining the stability and reliability of the platform for production users that prefer to receive features after they have been validated by Google and other developers that use the pre-release builds.
|
||||
|
||||
这种发布节奏能让你尽快用上已就绪的新特性,同时,为生产环境下的用户维护本平台的稳定性和可靠性。
|
||||
这种发布的节奏能让渴望新功能的开发者在这些功能开发开发完成并通过我们的代码审查和集成测试流程后立即就可以使用,同时为那些喜欢在新功能经过 Google 和其他使用预发布版本的开发人员的验证后才采纳的生产环境用户,保持平台的稳定性和可靠性。
|
||||
|
||||
{@a lts}
|
||||
{@a support}
|
||||
|
|
|
@ -15,7 +15,7 @@ It includes information about prerequisites, installing the CLI, creating an ini
|
|||
|
||||
If you are new to Angular, you might want to start with [Try it now!](start), which introduces the essentials of Angular in the context of a ready-made basic online store app that you can examine and modify. This standalone tutorial takes advantage of the interactive [StackBlitz](https://stackblitz.com/) environment for online development. You don't need to set up your local environment until you're ready.
|
||||
|
||||
如果你不熟悉 Angular,请参阅[快速上手](start)。在构建基本版在线商店应用的过程中,快速上手可以帮助你快速学习 Angular 的基本知识。它充分利用了 [StackBlitz](https://stackblitz.com/) 在线开发环境,因此在你准备就绪之前,都不需要建立本地环境。
|
||||
如果你不熟悉Angular,可能要从[立即尝试!](start)开始,它可以在查看和修改一个现成的基础版在线商店的上下文中介绍 Angular 的要点。这个独立的教程利用交互式的 [StackBlitz](https://stackblitz.com/) 环境进行在线开发。在你准备好这些之前,无需设置本地环境。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -183,7 +183,7 @@ You will see:
|
|||
|
||||
* Work through the [Tour of Heroes Tutorial](tutorial), a complete hands-on exercise that introduces you to the app development process using the Angular CLI and walks through important subsystems.
|
||||
|
||||
走一遍[英雄指南教程](tutorial),这是一个完整的动手练习题,它将教你使用 Angular CLI 进行应用开发的过程,并逐步介绍重要的子系统。
|
||||
过一遍[英雄指南教程](tutorial),这是一个完整的动手练习题,它将教你使用 Angular CLI 进行应用开发的过程,并逐步介绍重要的子系统。
|
||||
|
||||
* To learn more about using the Angular CLI, see the [CLI Overview](cli "CLI Overview"). In addition to creating the initial workspace and app scaffolding, you can use the CLI to generate Angular code such as components and services. The CLI supports the full development cycle, including building, testing, bundling, and deployment.
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ The following sections provide detailed information on constraints, grammar,
|
|||
and translation of microsyntax.
|
||||
|
||||
当你编写自己的结构型指令时,也可以利用这些微语法机制。
|
||||
例如,Angular 中的微语法允许你写成 `<div *ngFor="let item of items">{{item}}</div>` 而不是 `<ng-template ngFor [ngForOf]="items"><div>{{item}}</div></ng-template>`。
|
||||
例如,Angular 中的微语法允许你写成 `<div *ngFor="let item of items">{{item}}</div>` 而不是 `<ng-template ngFor let-item [ngForOf]="items"><div>{{item}}</div></ng-template>`。
|
||||
以下各节提供了有关约束、语法和微语法翻译方式的详细信息。
|
||||
|
||||
### Constraints
|
||||
|
|
|
@ -73,6 +73,7 @@ For example, `hero.component.ts` and `hero.component.html`.
|
|||
The guideline uses the shortcut `hero.component.ts|html|css|spec` to represent those various files. Using this shortcut makes this guide's file structures easier to read and more terse.
|
||||
|
||||
本指南将会使用像 `hero.component.ts|html|css|spec` 的简写来表示上面描述的多个文件,目的是保持本指南的简洁性,增加描述文件结构时的可读性。
|
||||
|
||||
{@a single-responsibility}
|
||||
|
||||
## Single responsibility
|
||||
|
|
|
@ -402,11 +402,11 @@ The template statement parser differs from the template expression parser and
|
|||
specifically supports both basic assignment (`=`) and chaining expressions with <code>;</code>.
|
||||
|
||||
和模板表达式一样,模板*语句*使用的语言也像 JavaScript。
|
||||
模板语句解析器和模板表达式解析器有所不同,特别之处在于它支持基本赋值 (`=`) 和表达式链 (`;` 和 `,`)。
|
||||
模板语句解析器和模板表达式解析器有所不同,特别之处在于它支持基本赋值 (`=`) 和表达式链 (`;`)。
|
||||
|
||||
However, certain JavaScript and template expression syntax is not allowed:
|
||||
|
||||
然而,某些 JavaScript 语法仍然是不允许的:
|
||||
然而,某些 JavaScript 语法和模板表达式语法仍然是不允许的:
|
||||
|
||||
* <code>new</code>
|
||||
|
||||
|
@ -422,11 +422,11 @@ However, certain JavaScript and template expression syntax is not allowed:
|
|||
|
||||
* the bitwise operators, such as `|` and `&`
|
||||
|
||||
位运算符 `|` 和 `&`
|
||||
位运算符,例如 `|` 和 `&`
|
||||
|
||||
* the [pipe operator](guide/template-syntax#pipe)
|
||||
|
||||
[模板表达式运算符](guide/template-syntax#expression-operators)
|
||||
[管道运算符](guide/template-syntax#expression-operators)
|
||||
|
||||
### Statement context
|
||||
|
||||
|
@ -1260,13 +1260,13 @@ the syntax and thinking are the same.
|
|||
|
||||
In this scenario, `ItemListComponent` is nested within `AppComponent` and the `items` property expects an array of objects.
|
||||
|
||||
在这种情况下,`ListItemComponent` 嵌套在 `AppComponent` 中,并且 `item` 属性需要一个对象。
|
||||
在这种情况下,`ItemListComponent` 嵌套在 `AppComponent` 中,并且 `items` 属性需要一个对象数组。
|
||||
|
||||
<code-example path="property-binding/src/app/app.component.html" region="pass-object" header="src/app/app.component.html"></code-example>
|
||||
|
||||
The `items` property is declared in the `ItemListComponent` with a type of `Item` and decorated with `@Input()`:
|
||||
|
||||
`item` 属性是在 `ListItemComponent` 中用 `Item` 类型声明的,并带有 `@Input()` 装饰器:
|
||||
`items` 属性是在 `ItemListComponent` 中用 `Item` 类型声明的,并带有 `@Input()` 装饰器:
|
||||
|
||||
<code-example path="property-binding/src/app/item-list/item-list.component.ts" region="item-input" header="src/app/item-list.component.ts"></code-example>
|
||||
|
||||
|
@ -1285,13 +1285,13 @@ specify a different item in `app.component.ts` so that the new item will render:
|
|||
|
||||
You just have to make sure, in this case, that you're supplying an array of objects because that's the type of `Item` and is what the nested component, `ItemListComponent`, expects.
|
||||
|
||||
在这个例子中,你只需要确保你所提供的对象的类型,也就是这个 `item` 的类型是嵌套组件 `ListItemComponent` 所需要的类型。
|
||||
在这个例子中,你只需要确保你所提供的对象数组的类型,也就是这个 `Item` 的类型是嵌套组件 `ItemListComponent` 所需要的类型。
|
||||
|
||||
In this example, `AppComponent` specifies a different `item` object
|
||||
(`currentItems`) and passes it to the nested `ItemListComponent`. `ItemListComponent` was able to use `currentItems` because it matches what an `Item` object is according to `item.ts`. The `item.ts` file is where
|
||||
`ItemListComponent` gets its definition of an `item`.
|
||||
|
||||
在此示例中,`AppComponent` 指定了另一个 `item` 对象( `currentItem` )并将其传给嵌套的 `ListItemComponent`。`ListItemComponent` 之所以能够使用 `currentItem` 是因为它与 `item.ts` 中定义的 `Item` 对象的类型相匹配。在 `item.ts` 文件中,`ListItemComponent` 获得了其对 `item` 的定义。
|
||||
在此示例中,`AppComponent` 指定了另一个 `item` 对象( `currentItems` )并将其传给嵌套的 `ItemListComponent`。`ItemListComponent` 之所以能够使用 `currentItems` 是因为它与 `item.ts` 中定义的 `Item` 对象的类型相匹配。在 `item.ts` 文件中,`ItemListComponent` 获得了其对 `item` 的定义。
|
||||
|
||||
### Remember the brackets
|
||||
|
||||
|
@ -1342,7 +1342,7 @@ not a template expression. Angular sets it and forgets about it.
|
|||
|
||||
The `[item]` binding, on the other hand, remains a live binding to the component's `currentItems` property.
|
||||
|
||||
另一方面,`[item]` 绑定仍然是与组件的 `currentItem` 属性的实时绑定。
|
||||
另一方面,`[item]` 绑定仍然是与组件的 `currentItems` 属性的实时绑定。
|
||||
|
||||
### Property binding vs. interpolation
|
||||
|
||||
|
@ -3623,7 +3623,7 @@ Angular 的非空断言运算符 `!` 在 Angular 模板中具有相同的目的
|
|||
When the Angular compiler turns your template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `item.color` might be `null` or `undefined`.
|
||||
|
||||
当 Angular 编译器把你的模板转换成 TypeScript 代码时,它会防止 TypeScript 不要报告此 `item` 可能为 `null` 或 `undefined` 的错误。
|
||||
当 Angular 编译器把你的模板转换成 TypeScript 代码时,它会防止 TypeScript 不要报告此 `item.color` 可能为 `null` 或 `undefined` 的错误。
|
||||
|
||||
Unlike the [_safe navigation operator_](guide/template-syntax#safe-navigation-operator "Safe navigation operator (?)"),
|
||||
the non-null assertion operator does not guard against `null` or `undefined`.
|
||||
|
|
|
@ -368,7 +368,7 @@ First, enabling `strictNullChecks` and including `null` in an input's type, as a
|
|||
Additionally, it is possible to provide type hints that are specific to the template type checker. See [Improving template type checking for custom directives](guide/structural-directives#directive-type-checks), and [Input setter coercion](#input-setter-coercion) below.
|
||||
|
||||
作为库作者,你可以采取多种措施为用户提供最佳体验。首先,启用 `strictNullChecks` 并在输入的类型中包括 `null`(如果适用),可以与消费者沟通,看他们是否可以提供可空的值。
|
||||
此外,可以提供特定模板类型检查器的类型提示,请参阅本指南的 [输入设置器强制转型](guide/template-typecheck#input-setter-coercion)部分。
|
||||
此外,可以提供特定模板类型检查器的类型提示,请参阅本指南的[为自定义指令改进模板类型检查](guide/structural-directives#directive-type-checks)和[输入设置器强制转型](guide/template-typecheck#input-setter-coercion)部分。
|
||||
|
||||
{@a input-setter-coercion}
|
||||
|
||||
|
|
|
@ -776,12 +776,11 @@ toggles the light's _on/off_ state and sets the message appropriately.
|
|||
|
||||
This component class has no dependencies. To test these types of classes, follow the same steps as you would for a service that has no dependencies:
|
||||
|
||||
该组件类没有依赖。
|
||||
要测试一个没有依赖的服务,可以咨询与无依赖的服务相同的步骤:
|
||||
该组件类没有依赖。要测试这些类,请遵循与测试那些无依赖服务相同的步骤:
|
||||
|
||||
1. Create a component using the new keyword.
|
||||
|
||||
创建一个使用新关键字的组件。
|
||||
使用 `new` 关键子创建一个组件。
|
||||
|
||||
2. Poke at its API.
|
||||
|
||||
|
@ -1903,13 +1902,14 @@ You do have to call [tick()](api/core/testing/tick) to advance the (virtual) clo
|
|||
Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish.
|
||||
In this case, it waits for the error handler's `setTimeout()`.
|
||||
|
||||
调用 `tick()` 会模拟时光的流逝,直到所有未决的异步活动都结束为止。
|
||||
调用 [`tick()`](api/core/testing/tick) 会模拟时光的流逝,直到所有未决的异步活动都结束为止。
|
||||
在这个例子中,它会等待错误处理器中的 `setTimeout()`。
|
||||
|
||||
The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) represents whether to invoke new generated macro tasks when ticking.
|
||||
|
||||
`tick()` 函数接受一个毫秒值作为参数(如果没有提供则默认为 0)。该参数表示虚拟时钟要前进多少。
|
||||
[tick()](api/core/testing/tick) 函数接受一个毫秒值和一个 `tickOptions` 作为参数(如果没有提供毫秒值则默认为 0)。该参数表示虚拟时钟要前进多少。
|
||||
比如,如果你的 `fakeAsync()` 测试中有一个 `setTimeout(fn, 100)` 函数,你就需要用 `tick(100)` 来触发它的 fn 回调。
|
||||
`tickOptions` 是一个可选参数,具有名为 `processNewMacroTasksSynchronously`(默认为 `true`)的属性,表示是否要在滴答时调用新生成的宏任务。
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/demo/async-helper.spec.ts"
|
||||
|
@ -1919,7 +1919,7 @@ The [tick()](api/core/testing/tick) function accepts milliseconds and tickOption
|
|||
The [tick()](api/core/testing/tick) function is one of the Angular testing utilities that you import with `TestBed`.
|
||||
It's a companion to `fakeAsync()` and you can only call it within a `fakeAsync()` body.
|
||||
|
||||
`tick()` 函数是你从 `TestBed` 中导入的 Angular 测试实用工具之一。
|
||||
[tick()](api/core/testing/tick) 函数是你从 `TestBed` 中导入的 Angular 测试实用工具之一。
|
||||
它和 `fakeAsync()` 一同使用,并且你只能在 `fakeAsync()` 体中调用它。
|
||||
|
||||
#### tickOptions
|
||||
|
@ -2029,7 +2029,7 @@ If you run other macro tasks such as `HTMLCanvasElement.toBlob()`, an _"Unknown
|
|||
If you want to support such a case, you need to define the macro task you want to support in `beforeEach()`.
|
||||
For example:
|
||||
|
||||
如果你要支持这种情况,就要在 `beforeEach()` 中定义你要支持的 `macroTask`。比如:
|
||||
如果你要支持这种情况,就要在 `beforeEach()` 中定义你要支持的宏任务。比如:
|
||||
|
||||
<code-example
|
||||
header="src/app/shared/canvas.component.spec.ts (excerpt)"
|
||||
|
@ -2982,7 +2982,7 @@ for the `id` to change during its lifetime.
|
|||
|
||||
The [ActivatedRoute in action](guide/router#activated-route-in-action) section of the [Router](guide/router) guide covers `ActivatedRoute.paramMap` in more detail.
|
||||
|
||||
[路由与导航](guide/router#route-parameters)一章中详细讲解了 `ActivatedRoute.paramMap`。
|
||||
[路由与导航](guide/router#route-parameters)一章的 [ActivatedRoute 实战](guide/router#activated-route-in-action)部分详细讲解了 `ActivatedRoute.paramMap`。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -5579,15 +5579,15 @@ as the application source code files that they test:
|
|||
|
||||
#### Place your spec files in a test folder
|
||||
|
||||
#### 什么时候我该把测试文件放进单独的 `test` 文件夹中?
|
||||
#### 把测试文件放进 `test` 文件夹中
|
||||
|
||||
Application integration specs can test the interactions of multiple parts
|
||||
spread across folders and modules.
|
||||
They don't really belong to any part in particular, so they don't have a
|
||||
natural home next to any one file.
|
||||
|
||||
应用程序的整合测试 spec 文件可以测试横跨多个目录和模块的多个部分之间的互动。
|
||||
它们不属于任何部分,很自然,没有特别的地方存放它们。
|
||||
应用程序的集成测试 spec 文件可以测试横跨多个目录和模块的多个部分之间的互动。
|
||||
它们不属于任何部分,自然也没有专门的地方存放它们。
|
||||
|
||||
It's often better to create an appropriate folder for them in the `tests` directory.
|
||||
|
||||
|
@ -5608,7 +5608,7 @@ next to their corresponding helper files.
|
|||
It should test only a single unit. On a first glance, you should be able to understand
|
||||
what the test is testing. If it's doing more, then it doesn't belong here.
|
||||
|
||||
[组件类测试](#component-class-testing)应该保持非常干净和简单。它应该只测试一个单元。应该乍一看就能了解测试的内容。如果还要做更多事,那它就不属于这里。
|
||||
[组件类测试](#component-class-testing)应该保持非常干净和简单。它应该只测试一个单元。应该一眼就能了解测试的内容。如果还要做更多事,那它就不属于这里。
|
||||
|
||||
{@a q-end-to-end}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ The CLI schematic `@nguniversal/express-engine` performs the required steps, as
|
|||
**Note:** <live-example downloadOnly>Download the finished sample code</live-example>,
|
||||
which runs in a [Node.js® Express](https://expressjs.com/) server.
|
||||
|
||||
你可以[下载最终的范例代码](generated/zips/universal/universal.zip),并将其运行在一个 [Node.js® Express](https://expressjs.com/) 服务器中。
|
||||
**注意:** <live-example downloadOnly>下载已完成的范例代码</live-example>,并将其运行在一个 [Node.js® Express](https://expressjs.com/) 服务器中。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -48,7 +48,7 @@ In this example, the Angular CLI compiles and bundles the Universal version of t
|
|||
[Ahead-of-Time (AOT) compiler](guide/aot-compiler).
|
||||
A Node.js Express web server compiles HTML pages with Universal based on client requests.
|
||||
|
||||
在这个例子中,Angular CLI 使用 [预先(AoT)编译器](guide/aot-compiler)编译并打包了该应用的 Universal 版本。Node Express Web 服务器则会根据客户端的请求,利用 Universal 编译 HTML 页面。
|
||||
在这个例子中,Angular CLI 使用 [预先(AoT)编译器](guide/aot-compiler)编译并打包了该应用的 Universal 版本。Node.js Express Web 服务器则会根据客户端的请求,利用 Universal 编译 HTML 页面。
|
||||
|
||||
To create the server-side app module, `app.server.module.ts`, run the following CLI command.
|
||||
|
||||
|
@ -99,7 +99,7 @@ npm run dev:ssr
|
|||
Open a browser and navigate to http://localhost:4200/.
|
||||
You should see the familiar Tour of Heroes dashboard page.
|
||||
|
||||
打开浏览器,导航到 http://localhost:4000/。你会看到熟悉的“英雄指南”仪表盘页面。
|
||||
打开浏览器,导航到 http://localhost:4200/。你会看到熟悉的“英雄指南”仪表盘页面。
|
||||
|
||||
Navigation via `routerLinks` works correctly because they use the native anchor (`<a>`) tags.
|
||||
You can go from the Dashboard to the Heroes page and back.
|
||||
|
@ -284,12 +284,13 @@ The server ([Node.js Express](https://expressjs.com/) in this guide's example)
|
|||
passes client requests for application pages to the NgUniversal `ngExpressEngine`. Under the hood, this
|
||||
calls Universal's `renderModule()` function, while providing caching and other helpful utilities.
|
||||
|
||||
服务器(这个例子中使用的是 [Node Express](https://expressjs.com/) 服务器)会把客户端对应用页面的请求传给 NgUniversal 的 `ngExpressEngine`。在内部实现上,它会调用 Universal 的 `renderModule()` 函数,它还提供了缓存等有用的工具函数。
|
||||
服务器(这个例子中使用的是 [Node.js Express](https://expressjs.com/) 服务器)会把客户端对应用页面的请求传给 NgUniversal 的 `ngExpressEngine`。在内部实现上,它会调用 Universal 的 `renderModule()` 函数,它还提供了缓存等有用的工具函数。
|
||||
|
||||
The `renderModule()` function takes as inputs a *template* HTML page (usually `index.html`),
|
||||
an Angular *module* containing components, and a *route* that determines which components to display.
|
||||
|
||||
`renderModule()` 函数接受一个*模板* HTML 页面(通常是 `index.html`)、一个包含组件的 Angular *模块*和一个用于决定该显示哪些组件的*路由*作为输入。
|
||||
|
||||
The route comes from the client's request to the server.
|
||||
|
||||
该路由从客户端的请求中传给服务器。
|
||||
|
@ -352,11 +353,16 @@ The `ngExpressEngine()` function is a wrapper around Universal's `renderModule()
|
|||
requests into server-rendered HTML pages. It accepts an object with the following properties:
|
||||
|
||||
`ngExpressEngine()` 是对 Universal 的 `renderModule()` 函数的封装。它会把客户端请求转换成服务端渲染的 HTML 页面。
|
||||
你还要在某个适用于你服务端技术栈的*模板引擎*中调用这个函数。
|
||||
它接受一个具有下列属性的对象:
|
||||
|
||||
* `bootstrap`: The root `NgModule` or `NgModule` factory to use for bootstraping the app when rendering on the server. For the example app, it is `AppServerModule`. It's the bridge between the Universal server-side renderer and the Angular application.
|
||||
|
||||
`bootstrap`:在服务器上渲染时用于引导应用程序的根 `NgModule` 或 `NgModule` 工厂。对于这个示例应用,它是 `AppServerModule`。它是 Universal 服务端渲染器和 Angular 应用之间的桥梁。
|
||||
|
||||
* `extraProviders`: This is optional and lets you specify dependency providers that apply only when rendering the app on the server. You can do this when your app needs information that can only be determined by the currently running server instance.
|
||||
|
||||
`extraProviders`:这是可选的,可以让你指定仅在服务器渲染应用程序时才适用的依赖提供者。当你的应用需要某些只能由当前运行的服务器实例确定的信息时,可以执行此操作。
|
||||
|
||||
The `ngExpressEngine()` function returns a `Promise` callback that resolves to the rendered page.
|
||||
It's up to the engine to decide what to do with that page.
|
||||
This engine's `Promise` callback returns the rendered page to the web server,
|
||||
|
@ -424,7 +430,7 @@ Because we use routing, we can easily recognize the three types of requests and
|
|||
A Node.js Express server is a pipeline of middleware that filters and processes requests one after the other.
|
||||
You configure the Node.js Express server pipeline with calls to `server.get()` like this one for data requests.
|
||||
|
||||
Node Express 服务器是一系列中间件构成的管道,它会挨个对 URL 请求进行过滤和处理。
|
||||
Node.js Express 服务器是一系列中间件构成的管道,它会挨个对 URL 请求进行过滤和处理。
|
||||
你可以调用 `app.get()` 来配置 Express 服务器的管道,就像下面这个数据请求一样:
|
||||
|
||||
<code-example path="universal/server.ts" header="server.ts (data URL)" region="data-request"></code-example>
|
||||
|
@ -457,7 +463,7 @@ The following code filters for request URLs with no extensions and treats them a
|
|||
A single `server.use()` treats all other URLs as requests for static assets
|
||||
such as JavaScript, image, and style files.
|
||||
|
||||
单独的 `app.use()` 会处理所有其它 URL,比如对 JavaScript 、图片和样式表等静态资源的请求。
|
||||
单独的 `server.use()` 会处理所有其它 URL,比如对 JavaScript 、图片和样式表等静态资源的请求。
|
||||
|
||||
To ensure that clients can only download the files that they are permitted to see, put all client-facing asset files in
|
||||
the `/dist` folder and only honor requests for files from the `/dist` folder.
|
||||
|
@ -467,25 +473,37 @@ the `/dist` folder and only honor requests for files from the `/dist` folder.
|
|||
The following Node.js Express code routes all remaining requests to `/dist`, and returns a `404 - NOT FOUND` error if the
|
||||
file isn't found.
|
||||
|
||||
下列 Express 代码会把剩下的所有请求都路由到 `/dist` 目录下,如果文件未找到,就会返回 `404 - NOT FOUND`。
|
||||
下列 Node.js Express 代码会把剩下的所有请求都路由到 `/dist` 目录下,如果文件未找到,就会返回 `404 - NOT FOUND`。
|
||||
|
||||
<code-example path="universal/server.ts" header="server.ts (static files)" region="static"></code-example>
|
||||
|
||||
### Using absolute URLs for HTTP (data) requests on the server
|
||||
|
||||
### 在服务端使用绝对 URL 进行 HTTP(数据)请求
|
||||
|
||||
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data.
|
||||
These services send requests to _relative_ URLs such as `api/heroes`.
|
||||
In a server-side rendered app, HTTP URLs must be _absolute_ (for example, `https://my-server.com/api/heroes`).
|
||||
This means that the URLs must be somehow converted to absolute when running on the server and be left relative when running in the browser.
|
||||
|
||||
本教程的 `HeroService` 和 `HeroSearchService` 都委托 Angular 的 `HttpClient` 模块来获取应用数据。这些服务会向 `api/heroes` 之类的*相对* URL 发送请求。在服务端渲染的应用中,HTTP URL 必须是*绝对的*(例如,`https://my-server.com/api/heroes` )。这意味着当在服务器上运行时,URL 必须以某种方式转换为绝对 URL,而在浏览器中运行时,它们是相对 URL。
|
||||
|
||||
If you are using one of the `@nguniversal/*-engine` packages (such as `@nguniversal/express-engine`), this is taken care for you automatically.
|
||||
You don't need to do anything to make relative URLs work on the server.
|
||||
|
||||
如果你正在使用 `@nguniversal/*-engine` 包之一(例如 `@nguniversal/express-engine`),就会自动为帮你做这件事。你无需再做任何事情来让相对 URL 能在服务器上运行。
|
||||
|
||||
If, for some reason, you are not using an `@nguniversal/*-engine` package, you may need to handle it yourself.
|
||||
|
||||
如果出于某种原因,你没有使用 `@nguniversal/*-engine` 包,你可能需要亲自处理它。
|
||||
|
||||
The recommended solution is to pass the full request URL to the `options` argument of [renderModule()](api/platform-server/renderModule) or [renderModuleFactory()](api/platform-server/renderModuleFactory) (depending on what you use to render `AppServerModule` on the server).
|
||||
This option is the least intrusive as it does not require any changes to the app.
|
||||
Here, "request URL" refers to the URL of the request as a response to which the app is being rendered on the server.
|
||||
For example, if the client requested `https://my-server.com/dashboard` and you are rendering the app on the server to respond to that request, `options.url` should be set to `https://my-server.com/dashboard`.
|
||||
|
||||
建议的解决方案是将完整的请求 URL 传递给 [renderModule()](api/platform-server/renderModule) 或 [renderModuleFactory()](api/platform-server/renderModuleFactory) 的 `options` 参数(具体取决于你在服务器上渲染 `AppServerModule` 的目的)。此选项的侵入性最小,因为它不需要对应用进行任何更改。这里的“请求 URL” 是指当应用在服务器上渲染时的地址。例如,如果客户端请求了 `https://my-server.com/dashboard` 并且要在服务器上渲染该应用以响应该请求,那么 `options.url` 应设置为 `https://my-server.com/dashboard`。
|
||||
|
||||
Now, on every HTTP request made as part of rendering the app on the server, Angular can correctly resolve the request URL to an absolute URL, using the provided `options.url`.
|
||||
|
||||
现在,作为在服务端渲染应用的一部分,每次发送 HTTP 请求时,Angular 都可以使用这里提供的 `options.url` 正确地将请求 URL 解析为绝对 URL。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Updating to Angular version 9
|
||||
|
||||
# 更新到 Angular 版本 9
|
||||
# 更新到 Angular 9
|
||||
|
||||
This guide contains information related to updating to version 9 of Angular.
|
||||
|
||||
|
|
|
@ -1537,6 +1537,8 @@ And that's all you need do to get the full benefit of AOT for Angular apps!
|
|||
|
||||
这就是你为获取 Angular 应用的 AOT 优势所要做的一切。
|
||||
|
||||
-->
|
||||
|
||||
## PhoneCat Upgrade Tutorial
|
||||
|
||||
## PhoneCat 升级教程
|
||||
|
@ -1887,7 +1889,7 @@ Install type definitions for the existing libraries that
|
|||
you're using but that don't come with prepackaged types: AngularJS, AngularJS Material, and the
|
||||
Jasmine unit test framework.
|
||||
|
||||
还要为那些没有自带类型信息的库(比如 AngularJS 和 Jasmine)安装类型定义文件。
|
||||
还要为那些没有自带类型信息的库(比如 AngularJS、AngularJS Material 和 Jasmine)安装类型定义文件。
|
||||
|
||||
For the PhoneCat app, we can install the necessary type definitions by running the following command:
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ This tutorial introduces you to the essentials of Angular by walking you through
|
|||
To help you get started right away, this guide uses a simple ready-made application that you can examine and modify interactively (without having to [set up a local work environment](guide/setup-local "Setup guide")).
|
||||
|
||||
本教程将通过一个简单的电子商务网站,向你介绍 Angular 的基本知识。该网站具有商品名录、购物车和结账表单。
|
||||
为了帮助你更好地起步,本指南提供了一个已完成的简单应用,你可以在其中试验及互动。
|
||||
为了帮助你更好地起步,本指南提供了一个已完成的简单应用,你可以在其中试验及互动,而不用[建立本地开发环境](guide/setup-local "Setup guide")。
|
||||
|
||||
<div class="callout is-helpful">
|
||||
|
||||
|
@ -28,7 +28,7 @@ To help you get started right away, this guide uses a simple ready-made applicat
|
|||
|
||||
## Create the sample project
|
||||
|
||||
## 创建一个新项目
|
||||
## 创建范例项目
|
||||
|
||||
<h4>
|
||||
<live-example name="getting-started-v0" noDownload>点此在 StackBlitz 上创建一个新项目。</live-example>
|
||||
|
@ -102,7 +102,7 @@ If you go directly to the [StackBlitz online development environment](https://st
|
|||
|
||||
In actual development you will typically use the [Angular CLI](guide/glossary#command-line-interface-cli "Definition of CLI"), a powerful command-line tool that lets you generate and modify applications. For a full step-by-step guide that shows how to use the CLI to create a new project and all of its parts, see [Tutorial: Tour of Heroes](tutorial).
|
||||
|
||||
在实际开发中,通常会使用 [Angular CLI](guide/glossary#command-line-interface-cli),这是一个功能强大的命令行工具,可以让你生成和修改应用程序。有关更多信息,请参见 [CLI 概述](cli)。
|
||||
在实际开发中,通常会使用 [Angular CLI](guide/glossary#command-line-interface-cli),这是一个功能强大的命令行工具,可以让你生成和修改应用程序。如果需要一个完整的分步指南,来学习如何使用 CLI 创建新项目及其各种部件,请参见[英雄指南教程](tutorial)。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -148,7 +148,7 @@ To help you get going, the following steps use predefined product data from the
|
|||
|
||||
`*ngFor` is a "structural directive". Structural directives shape or reshape the DOM's structure, typically by adding, removing, and manipulating the elements to which they are attached. Directives with an asterisk, `*`, are structural directives.
|
||||
|
||||
`*ngFor` 是一个 "结构型指令"。结构型指令会通过添加、删除和操纵它们的宿主元素等方式塑造或重塑 DOM 的结构。任何带有星号 `*` 的指令都是结构型指令。
|
||||
`*ngFor` 是一个 "结构型指令"。结构型指令会通过添加、删除和操纵它们的宿主元素等方式塑造或重塑 DOM 的结构。带有星号 `*` 的指令都是结构型指令。
|
||||
</div>
|
||||
|
||||
1. To display the names of the products, use the interpolation syntax `{{ }}`. Interpolation renders a property's value as text. Inside the `<div>`, add an `<h3>` to display the interpolation of the product's name property:
|
||||
|
@ -259,7 +259,7 @@ In the process, you've learned to use five common features of Angular's template
|
|||
|
||||
For a fuller introduction to Angular's template syntax, see [Introduction to components and templates](guide/architecture-components#template-syntax "Template Syntax").
|
||||
|
||||
要了解关于 Angular 模板语法全部特性的信息,请参阅[模板语法指南](guide/template-syntax "模板语法")。
|
||||
对 Angular 模板语法全的完整介绍,请参阅[组件与模板简介](guide/architecture-components#template-syntax "模板语法")。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -347,7 +347,7 @@ The next section expands the app's capabilities by adding a new component—
|
|||
|
||||
For more information about components and how they interact with templates, see [Introduction to Components](guide/architecture-components "Concepts > Introduction to Components and Templates").
|
||||
|
||||
要了解关于组件及其与模板交互的更多信息,请参阅[“组件简介”](guide/architecture-components "架构>组件简介")。
|
||||
要了解关于组件及其与模板交互的更多信息,请参阅[“组件简介”](guide/architecture-components "概念>组件与模板介绍")。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -581,8 +581,8 @@ To continue exploring Angular, choose either of the following options:
|
|||
|
||||
* [Continue to the "In-app navigation" section](start/start-routing "Try it: In-app navigation") to create a product details page that can be accessed by clicking a product name and that has its own URL pattern.
|
||||
|
||||
[继续浏览“路由”部分](start/start-routing "入门:路由"),创建一个商品详情页面,通过单击商品名称,可以访问该页面,该页面有自己的 URL 模式。
|
||||
[继续浏览“应用内导航”部分](start/start-routing "入门:路由")以创建一个商品详情页面,通过单击商品名称,可以访问该页面,该页面有自己的 URL 模式。
|
||||
|
||||
* [Skip ahead to the "Deployment" section](start/start-deployment "Try it: Deployment") to move to local development, or deploy your app to Firebase or your own server.
|
||||
|
||||
[跳到“部署”部分,](start/start-deployment "入门:部署")把你的应用转移到本地开发、部署到 Firebase 或你自己的服务器。
|
||||
[跳到“部署”部分,](start/start-deployment "试一试:部署")把你的应用转移到本地开发、部署到 Firebase 或你自己的服务器。
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
At the end of [In-app Navigation](start/start-routing "Try it: In-app Navigation"), the online store application has a product catalog with two views: a product list and product details.
|
||||
Users can click on a product name from the list to see details in a new view, with a distinct URL, or route.
|
||||
|
||||
在[路由](start/start-routing "入门:路由")的末尾,本应用实现了一个包含两个视图的商品名录:商品列表和商品详情。用户点击清单中的某个商品名称,就会在新视图中看到具有专门的 URL 或路由的详情页。
|
||||
在[应用内导航](start/start-routing "试一试:应用内导航")的末尾,本应用实现了一个包含两个视图的商品名录:商品列表和商品详情。用户点击清单中的某个商品名称,就会在新视图中看到具有专门的 URL 或路由的详情页。
|
||||
|
||||
This page guides you through creating the shopping cart in three phases:
|
||||
|
||||
|
@ -13,7 +13,7 @@ This page guides you through creating the shopping cart in three phases:
|
|||
|
||||
* Update the product details view to include a "Buy" button, which adds the current product to a list of products that a cart service manages.
|
||||
|
||||
修改商品详情页,让它包含一个 “Buy” 按钮,它会把当前商品添加到由 "购物车服务" 管理的商品列表中。
|
||||
修改商品详情视图,让它包含一个 “Buy” 按钮,它会把当前商品添加到由 "购物车服务" 管理的商品列表中。
|
||||
|
||||
* Add a cart component, which displays the items in the cart.
|
||||
|
||||
|
@ -204,7 +204,7 @@ This section walks you through using the cart service to add a product to the ca
|
|||
|
||||
## Create the cart view
|
||||
|
||||
## 创建购物车页面
|
||||
## 创建购物车视图
|
||||
|
||||
At this point, users can put items in the cart by clicking "Buy", but they can't yet see their cart.
|
||||
|
||||
|
@ -212,11 +212,11 @@ At this point, users can put items in the cart by clicking "Buy", but they can't
|
|||
|
||||
Create the cart view in two steps:
|
||||
|
||||
分两步创建购物车页面:
|
||||
分两步创建购物车视图:
|
||||
|
||||
1. Create a cart component and configure routing to the new component. At this point, the cart view has only default text.
|
||||
|
||||
创建一个购物车组件并配置指向这个新组件的路由。此时,购物车页面只会显示默认文本。
|
||||
创建一个购物车组件并配置指向这个新组件的路由。此时,购物车视图只会显示默认文本。
|
||||
|
||||
1. Display the cart items.
|
||||
|
||||
|
@ -228,7 +228,7 @@ Create the cart view in two steps:
|
|||
|
||||
To create the cart view, begin by following the same steps you did to create the product details component and configure routing for the new component.
|
||||
|
||||
要创建购物车页面,首先要执行与创建商品详情组件相同的步骤,并为这个新组件设置路由。
|
||||
要创建购物车视图,首先要执行与创建商品详情组件相同的步骤,并为这个新组件设置路由。
|
||||
|
||||
1. Generate a cart component, named `cart`.
|
||||
|
||||
|
@ -346,7 +346,7 @@ You can use services to share data across components:
|
|||
|
||||
1. Click on "My Store" to go to the product list view.
|
||||
|
||||
点击“My Store”,进入商品列表页面。
|
||||
点击“My Store”,进入商品列表视图。
|
||||
|
||||
1. Click on a product name to display its details.
|
||||
|
||||
|
@ -376,7 +376,7 @@ You can use services to share data across components:
|
|||
|
||||
StackBlitz tip: Any time the preview refreshes, the cart is cleared. If you make changes to the app, the page refreshes, so you'll need to buy products again to populate the cart.
|
||||
|
||||
StackBlitz 提示:只要预览刷新,就会清除购物车。如果你对该应用进行了更改,页面就会刷新,你需要重新购买商品来填充购物车。
|
||||
StackBlitz 提示:只要预览刷新,就会清除购物车。如果你对该应用进行了更改,视图就会刷新,你需要重新购买商品来填充购物车。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -384,7 +384,7 @@ StackBlitz 提示:只要预览刷新,就会清除购物车。如果你对该
|
|||
|
||||
For more information about services, see [Introduction to Services and Dependency Injection](guide/architecture-services "Concepts > Intro to Services and DI").
|
||||
|
||||
要了解关于[服务](guide/architecture-services "架构>服务简介和 DI")的更多信息,请参阅[“服务和依赖注入简介”](guide/architecture-services "架构>服务简介和 DI")。
|
||||
要了解关于服务的更多信息,请参阅[“服务和依赖注入简介”](guide/architecture-services "概念>服务简介和 DI")。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -504,13 +504,13 @@ First, define a `get()` method.
|
|||
|
||||
For more information about Angular's `HttpClient`, see the [Client-Server Interaction](guide/http "Server interaction through HTTP") guide.
|
||||
|
||||
要了解关于 Angular `HttpClient` 的更多信息,请参阅[HttpClient 指南](guide/http "HttpClient 指南")。
|
||||
要了解关于 Angular `HttpClient` 的更多信息,请参阅[客户端-服务器集成](guide/http "HttpClient 指南")指南。
|
||||
|
||||
</div>
|
||||
|
||||
## Define the shipping view
|
||||
|
||||
## 定义配送页面
|
||||
## 定义配送视图
|
||||
|
||||
Now that your app can retrieve shipping data, create a shipping component and template.
|
||||
|
||||
|
@ -577,7 +577,7 @@ Now that your app can retrieve shipping data, create a shipping component and t
|
|||
|
||||
1. Add a link from the cart view to the shipping view:
|
||||
|
||||
在购物车页面中添加一个到配送页面的链接:
|
||||
在购物车视图中添加一个到配送视图的链接:
|
||||
|
||||
<code-example header="src/app/cart/cart.component.html" path="getting-started/src/app/cart/cart.component.2.html"></code-example>
|
||||
|
||||
|
@ -615,9 +615,9 @@ To continue exploring Angular, choose either of the following options:
|
|||
|
||||
* [Continue to the "Forms" section](start/start-forms "Try it: Forms for User Input") to finish the app by adding the shopping cart view and a checkout form.
|
||||
|
||||
[继续浏览“表单”部分](start/start-forms "入门:表单"),通过添加购物车页面和一个结账表单来完成该应用。
|
||||
[继续浏览“表单”部分](start/start-forms "试一试:用表单接收用户输入"),通过添加购物车视图和一个结账表单来完成该应用。
|
||||
|
||||
* [Skip ahead to the "Deployment" section](start/start-deployment "Try it: Deployment") to move to local development, or deploy your app to Firebase or your own server.
|
||||
|
||||
[跳到“部署”部分,](start/start-deployment "入门:部署")把你的应用部署到 Firebase 或转成本地开发。
|
||||
[跳到“部署”部分,](start/start-deployment "试一试:部署")把你的应用部署到 Firebase 或转成本地开发。
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ To deploy your application, you have to compile it, and then host the JavaScript
|
|||
|
||||
Whether you came here directly from [Part 1](start "Try it: A basic app"), or completed the entire online store application through the [In-app navigation](start/start-routing "Try it: In-app navigation"), [Manage data](start/start-data "Try it: Manage data"), and [Forms for user input](start/start-forms "Try it: Forms for user input") sections, you have an application that you can deploy by following the instructions in this section.
|
||||
|
||||
无论你是从[你的第一个应用](start "入门:你的第一个应用")直接来到这里,还是经过[路由](start/start-routing "入门:路由")、[管理数据](start/start-data "入门:管理数据")和[表单](start/start-forms "入门:表单")部分,完成了整个在线商店应用之后来到这里,都可以按照本节中的说明进行部署。
|
||||
无论你是从[第一部分](start "入门:你的第一个应用")直接来到这里,还是经过[应用内导航](start/start-routing "入门:路由")、[管理数据](start/start-data "入门:管理数据")和[用表单接收用户输入](start/start-forms "入门:表单")部分,完成了整个在线商店应用之后来到这里,都可以按照本节中的说明进行部署。
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -44,11 +44,11 @@ StackBlitz 项目默认是公开的,你可以通过项目的 URL 来共享你
|
|||
|
||||
To build your application locally or for production, download the source code from your StackBlitz project by clicking the `Download Project` icon in the left menu across from `Project` to download your files.
|
||||
|
||||
要在本地构建应用或未生产环境构建应用,你需要从 StackBlitz 项目中下载源代码。单击左侧菜单中的 `Download Project` 图标以下载文件。
|
||||
要在本地构建应用或未生产环境构建应用,就要从 StackBlitz 项目中下载源代码。单击左侧菜单中的 `Download Project` 图标以下载文件。
|
||||
|
||||
Once you have the source code downloaded and unzipped, use the [Angular Console](https://angularconsole.com "Angular Console web site") to serve the application, or install `Node.js` and serve your app with the Angular CLI.
|
||||
|
||||
下载并解压源代码后,就可以使用 [Angular Console](https://angularconsole.com "Angular Console 的网站") 来启动开发服务器了,也可以先安装 `Node.js` 再安装 Angular CLI。
|
||||
下载并解压源代码后,就可以使用 [Angular Console](https://angularconsole.com "Angular Console 的网站") 来启动开发服务器了,也可以先安装 `Node.js` 再使用 Angular CLI 来启动开发服务器。
|
||||
|
||||
From the terminal, install the Angular CLI globally with:
|
||||
|
||||
|
@ -72,7 +72,7 @@ ng new my-project-name
|
|||
|
||||
In your new CLI generated app, replace the `/src` folder with the one from your `StackBlitz` download, and then perform a build.
|
||||
|
||||
进入你从 `StackBlitz` 下载的 `/src` 文件夹,然后执行 build 命令。
|
||||
在 CLI 生成的新应用中,将其 `/src` 目录替换成你从 `StackBlitz` 下载的同名目录,然后进行构建。
|
||||
|
||||
```sh
|
||||
ng build --prod
|
||||
|
@ -96,7 +96,7 @@ If the above `ng build` command throws an error about missing packages, append t
|
|||
|
||||
The files in the `dist/my-project-name` folder are static. This means you can host them on any web server capable of serving files (such as `Node.js`, Java, .NET), or any backend (such as Firebase, Google Cloud, or App Engine).
|
||||
|
||||
`dist/my-project-name` 文件夹中的文件都是静态的,可以托管在任何能够提供文件服务的 Web 服务器上(`Node.js`,Java,.NET),也可以是任何后端(Firebase,Google Cloud,App Engine 等)。
|
||||
`dist/my-project-name` 文件夹中的文件都是静态的,可以托管在任何能够提供文件服务的 Web 服务器上(比如 `Node.js`,Java,.NET),也可以是任何后端(比如 Firebase,Google Cloud,App Engine 等)。
|
||||
|
||||
### Hosting an Angular app on Firebase
|
||||
|
||||
|
@ -116,7 +116,8 @@ One of the easiest ways to get your site live is to host it using Firebase.
|
|||
|
||||
1. Add the `@angular/fire` schematics that will handle your deployment using `ng add @angular/fire`.
|
||||
|
||||
使用 `npm install -g firebase-tools` 安装 `firebase-tools` CLI 来处理你的部署。
|
||||
添加 `@angular/fire` 原理图,它将使用 `ng add @angular/fire` 来处理你的发布。
|
||||
|
||||
1. Connect your CLI to your Firebase account and initialize the connection to your project using `firebase login` and `firebase init`.
|
||||
|
||||
把你的 CLI 和 Firebase 帐户联系起来,使用 `firebase login` 和 `firebase init` 来初始化这个联系。
|
||||
|
@ -139,7 +140,8 @@ One of the easiest ways to get your site live is to host it using Firebase.
|
|||
|
||||
1. Deploy your application with `ng deploy`.
|
||||
|
||||
用 `firebase deploy` 命令部署你的应用,这是因为 `firebase init` 命令已经创建了一个 `firebase.json`,它会告诉 Firebase 如何用你的应用提供服务。
|
||||
用 `ng deploy` 命令部署你的应用。
|
||||
|
||||
1. Once deployed, visit https://your-firebase-project-name.firebaseapp.com to see it live!
|
||||
|
||||
部署之后,访问 <https://your-firebase-project-name.firebaseapp.com> 进行实时查看!
|
||||
|
@ -156,11 +158,11 @@ Read more about development and distribution of your application in the [Buildin
|
|||
|
||||
## Join the Angular community
|
||||
|
||||
## 加入我们的社区
|
||||
## 加入 Angular 社区
|
||||
|
||||
You are now an Angular developer! [Share this moment](https://twitter.com/intent/tweet?url=https://angular.io/start&text=I%20just%20finished%20the%20Angular%20Getting%20Started%20Tutorial "Angular on Twitter"), tell us what you thought of this get-started exercise, or submit [suggestions for future editions](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form").
|
||||
|
||||
你现在是一位 Angular 的开发者了![分享这一刻](https://twitter.com/intent/tweet?url=https://next.angular.io/getting-started&text=I%20just%20finished%20the%20Angular%20Getting%20Started%20Tutorial "Angular on Twitter"),告诉我们你对这份“入门文档”的看法,或者[为今后的版本](https://github.com/angular/angular/issues/new/choose "Angular GitHub 存储库中的新问题表单")提交[建议](https://github.com/angular/angular/issues/new/choose "Angular GitHub 存储库中的新问题表单")。
|
||||
你现在是一位 Angular 的开发者了![分享这一刻](https://twitter.com/intent/tweet?url=https://next.angular.io/getting-started&text=I%20just%20finished%20the%20Angular%20Getting%20Started%20Tutorial "Angular on Twitter"),告诉我们你对这份“快速上手”的看法,或者[为今后的版本](https://github.com/angular/angular/issues/new/choose "Angular GitHub 存储库中的新问题表单")提交[建议](https://github.com/angular/angular/issues/new/choose "Angular GitHub 存储库中的新问题表单")。
|
||||
|
||||
Angular offers many more capabilities, and you now have a foundation that empowers you to build an application and explore those other capabilities:
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ Now that you've defined the form model in the component class, you need a checko
|
|||
|
||||
Use the following steps to add a checkout form at the bottom of the "Cart" view.
|
||||
|
||||
使用下列步骤在“购物车”页面的底部添加一个结帐表单。
|
||||
使用下列步骤在“购物车”视图的底部添加一个结帐表单。
|
||||
|
||||
1. Open `cart.component.html`.
|
||||
|
||||
|
@ -142,5 +142,5 @@ Congratulations! You have a complete online store application with a product cat
|
|||
|
||||
[Continue to the "Deployment" section](start/start-deployment "Try it: Deployment") to move to local development, or deploy your app to Firebase or your own server.
|
||||
|
||||
[继续浏览“部署”部分,](start/start-deployment "入门:部署")把你的应用转移到本地开发、部署到 Firebase 或你自己的服务器。
|
||||
[继续浏览“部署”部分,](start/start-deployment "试一试:部署")把你的应用转移到本地开发、部署到 Firebase 或你自己的服务器。
|
||||
|
||||
|
|
|
@ -6,15 +6,15 @@ At the end of [part 1](start "Get started with a basic Angular app"), the online
|
|||
The app doesn't have any variable states or navigation.
|
||||
There is one URL, and that URL always displays the "My Store" page with a list of products and their descriptions.
|
||||
|
||||
在[你的第一个应用](start "入门:你的第一个应用")结束时,这个在线商店应用会有一个基本的商品名录。该应用还没有任何可变的状态或导航。它只有一个 URL,该 URL 总是会显示“我的商店”页面,其中是商品列表及其描述。
|
||||
在[第一部分](start "入门:你的第一个应用")结束时,这个在线商店应用会有一个基本的商品名录。该应用还没有任何可变的状态或导航。它只有一个 URL,该 URL 总是会显示“我的商店”页面,其中是商品列表及其描述。
|
||||
|
||||
This guide shows you how to use Angular [routing](guide/glossary#router "Router definition") to give the user in-app navigation. In a single-page app, instead of loading new pages, you show different components and data to the user based on where the user is in the application.
|
||||
|
||||
本指南会教你如何使用 Angular 路由器来用一些独立页面显示完整的产品详情,这些页面有自己的 URL。
|
||||
本指南会告诉你如何使用 Angular [路由](guide/glossary#router "Router definition")来让用户进行应用内导航。在单页面应用中,你不会重新加载新页面,而是根据用户所在的位置,向他显示不同的组件和数据。
|
||||
|
||||
The router lets you display full product details in separate [views](guide/glossary#view "View definition"), each with its own URL. Routing enables navigation from one view to the next (within the same page) as users perform tasks such as the following:
|
||||
|
||||
Angular [路由器](guide/glossary#router "Router definition")能让你根据用户在应用中的位置向用户显示不同的组件和数据。当用户执行应用任务时,路由器可以从一个视图导航到另一个视图。比如:
|
||||
Angular [路由器](guide/glossary#router "Router definition")能让你在不同的[视图](guide/glossary#view "View definition")中显示产品的详情,每个产品都有自己的 URL。当用户执行应用任务时,路由器可以从一个视图导航到另一个视图(但在同一个页面)。比如:
|
||||
|
||||
* Entering a URL in the address bar to navigate to a corresponding view.
|
||||
|
||||
|
@ -23,6 +23,7 @@ Angular [路由器](guide/glossary#router "Router definition")能让你根据用
|
|||
* Clicking links on the page to navigate to a new view.
|
||||
|
||||
点击页面上的链接,导航到新页面。
|
||||
|
||||
* Clicking the browser's back and forward buttons to navigate backward and forward through the browser history.
|
||||
|
||||
点击浏览器的后退和前进按钮,在浏览器的历史中前后导航。
|
||||
|
@ -33,7 +34,7 @@ Angular [路由器](guide/glossary#router "Router definition")能让你根据用
|
|||
|
||||
The app is already set up to use the Angular `Router` and to use routing to navigate to the product list component you modified earlier. This section shows you how to define a route to show individual product details.
|
||||
|
||||
该应用已经设置为使用 Angular 路由器,并通过路由导航到之前修改过的商品列表组件。本节会向你展示如何定义一个可以显示单个商品详情的路由。
|
||||
该应用已经设置为使用 Angular `Router`,并通过路由导航到之前修改过的商品列表组件。本节会向你展示如何定义一个可以显示单个商品详情的路由。
|
||||
|
||||
1. Generate a new component for product details. Give the component the name `product-details`.
|
||||
|
||||
|
@ -126,7 +127,7 @@ The product details component handles the display of each product. The Angular R
|
|||
|
||||
By injecting the `ActivatedRoute`, you are configuring the component to use a *service*. The [Managing Data](start/start-data "Try it: Managing Data") page covers services in more detail.
|
||||
|
||||
通过注入 `ActivatedRoute`,你把该组件配置成了使用服务的。《快速上手》教程中的这部分只是简略使用了该语法,在[管理数据](start/start-data "Getting Started: Managing Data")部分深入讲解了服务的更多细节。
|
||||
通过注入 `ActivatedRoute`,你把该组件配置成了使用服务的。《快速上手》教程中的这部分只是简略使用了该语法,在[管理数据](start/start-data "试一试: 管理数据")部分深入讲解了服务的更多细节。
|
||||
|
||||
1. In the `ngOnInit()` method, subscribe to route parameters and fetch the product based on the `productId`.
|
||||
|
||||
|
@ -173,6 +174,7 @@ Congratulations! You have integrated routing into your online store.
|
|||
* Products are linked from the product list view to individual products.
|
||||
|
||||
从商品列表页面链接到了单个商品。
|
||||
|
||||
* Users can click on a product name from the list to see details in a new view, with a distinct URL/route.
|
||||
|
||||
用户可以点击列表中的某个商品名称来在新视图中查看其详细信息,并带有显著的 URL/路由。
|
||||
|
|
|
@ -43,15 +43,16 @@ By the end of this tutorial you will be able to do the following:
|
|||
|
||||
* Use built-in Angular [directives](guide/glossary#directive "Directives definition") to show and hide elements and display lists of hero data.
|
||||
|
||||
使用 Angular 的内置指令来显示 / 隐藏元素,并显示英雄数据的列表。
|
||||
使用 Angular 的内置[指令](guide/glossary#directive "Directives definition")来显示 / 隐藏元素,并显示英雄数据的列表。
|
||||
|
||||
* Create Angular [components](guide/glossary#component "Components definition") to display hero details and show an array of heroes.
|
||||
|
||||
创建 Angular 组件以显示英雄的详情,并显示一个英雄数组。
|
||||
创建 Angular [组件](guide/glossary#component "Components definition")以显示英雄的详情,并显示一个英雄数组。
|
||||
|
||||
* Use one-way [data binding](guide/glossary#data-binding "Data binding definition") for read-only data.
|
||||
|
||||
为只读数据使用单向数据绑定。
|
||||
为只读数据使用单向[数据绑定](guide/glossary#data-binding "Data binding definition")。
|
||||
|
||||
* Add editable fields to update a model with two-way data binding.
|
||||
|
||||
添加可编辑字段,使用双向数据绑定来更新模型。
|
||||
|
@ -63,17 +64,18 @@ By the end of this tutorial you will be able to do the following:
|
|||
* Enable users to select a hero from a master list and edit that hero in the details view.
|
||||
|
||||
让用户可以在主列表中选择一个英雄,然后在详情视图中编辑他。
|
||||
|
||||
* Format data with [pipes](guide/glossary#pipe "Pipe definition").
|
||||
|
||||
使用管道来格式化数据。
|
||||
使用[管道](guide/glossary#pipe "Pipe definition")来格式化数据。
|
||||
|
||||
* Create a shared [service](guide/glossary#service "Service definition") to assemble the heroes.
|
||||
|
||||
创建共享的服务来管理这些英雄。
|
||||
创建共享的[服务](guide/glossary#service "Service definition")来管理这些英雄。
|
||||
|
||||
* Use [routing](guide/glossary#router "Router definition") to navigate among different views and their components.
|
||||
|
||||
使用路由在不同的视图及其组件之间导航。
|
||||
使用[路由](guide/glossary#router "Router definition")在不同的视图及其组件之间导航。
|
||||
|
||||
You'll learn enough Angular to get started and gain confidence that
|
||||
Angular can do whatever you need it to do.
|
||||
|
|
|
@ -216,10 +216,10 @@ When the user clicks in the `<li>`, Angular executes the `onSelect(hero)` expres
|
|||
`click` 外面的圆括号会让 Angular 监听这个 `<li>` 元素的 `click` 事件。
|
||||
当用户点击 `<li>` 时,Angular 就会执行表达式 `onSelect(hero)`。
|
||||
|
||||
`onSelect()` method in `HeroesComponent` to
|
||||
In the next section, define an `onSelect()` method in `HeroesComponent` to
|
||||
display the hero that was defined in the `*ngFor` expression.
|
||||
|
||||
`HeroesComponent` 上的 `onSelect()` 方法 用来显示 `*ngFor` 表达式所定义的那个英雄(`hero`)。
|
||||
下一部分,会在 `HeroesComponent` 上定义一个 `onSelect()` 方法,用来显示 `*ngFor` 表达式所定义的那个英雄(`hero`)。
|
||||
|
||||
### Add the click event handler
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
### Using absolute URLs for HTTP (data) requests on the server
|
||||
|
||||
### 在服务器端使用HTTP(数据)请求的绝对URL
|
||||
|
||||
|
||||
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data.
|
||||
These services send requests to *relative* URLs such as `api/heroes`.
|
||||
In a server-side rendered app, HTTP URLs must be *absolute* (for example, `https://my-server.com/api/heroes`).
|
||||
This means that the URLs must be somehow converted to absolute when running on the server and be left relative when running in the browser.
|
||||
|
||||
本教程的`HeroService`和`HeroSearchService`委托给Angular `HttpClient`模块来获取应用数据。这些服务会向`api/heroes`类的*相对* URL发送请求。在服务器端呈现的应用中,HTTP URL必须是*绝对的* (例如, `https://my-server.com/api/heroes` )。这意味着当在服务器上运行时,URL必须以某种方式转换为绝对值,并且当在浏览器中运行时,它们是相对的。
|
||||
|
||||
|
||||
If you are using one of the `@nguniversal/*-engine` packages (such as `@nguniversal/express-engine`), this is taken care for you automatically.
|
||||
You don't need to do anything to make relative URLs work on the server.
|
||||
|
||||
如果你正在使用其中一个`@nguniversal/*-engine`软件包(例如`@nguniversal/express-engine` ),这会自动为你服务。你无需做任何事情来让相对URL在服务器上运行。
|
||||
|
||||
|
||||
If, for some reason, you are not using an `@nguniversal/*-engine` package, you may need to handle it yourself.
|
||||
|
||||
如果,出于某种原因,你没有使用`@nguniversal/*-engine`包,你可能需要亲自处理它。
|
||||
|
||||
|
||||
The recommended solution is to pass the full request URL to the `options` argument of [renderModule()](api/platform-server/renderModule) or [renderModuleFactory()](api/platform-server/renderModuleFactory) (depending on what you use to render `AppServerModule` on the server).
|
||||
This option is the least intrusive as it does not require any changes to the app.
|
||||
Here, "request URL" refers to the URL of the request as a response to which the app is being rendered on the server.
|
||||
For example, if the client requested `https://my-server.com/dashboard` and you are rendering the app on the server to respond to that request, `options.url` should be set to `https://my-server.com/dashboard`.
|
||||
|
||||
建议的解决方案是将完整的请求URL传递给[renderModule()](api/platform-server/renderModule)或[renderModuleFactory()](api/platform-server/renderModuleFactory)的`options`参数(具体取决于你在服务器上渲染`AppServerModule`用途)。此选项的侵入性最小,因为它不需要对应用进行任何更改。这里,“request URL”指的是请求的URL,作为应用在服务器上呈现的响应。例如,如果客户端请求了`https://my-server.com/dashboard`并且要在服务器上渲染该应用来响应该请求,那么`options.url`应设置为`https://my-server.com/dashboard` 。
|
||||
|
||||
|
||||
Now, on every HTTP request made as part of rendering the app on the server, Angular can correctly resolve the request URL to an absolute URL, using the provided `options.url`.
|
||||
|
||||
现在,作为在服务器上呈现应用的一部分,每次HTTP请求,Angular都可以使用提供的`options.url`正确地将请求URL解析为绝对URL。
|
||||
|
Loading…
Reference in New Issue