refactor: 重构自动翻译代码

This commit is contained in:
Zhicheng Wang 2018-03-24 16:33:17 +08:00
parent 6c3d57aee9
commit e167fa5229
80 changed files with 9875 additions and 2961 deletions

View File

@ -62,9 +62,7 @@ The following table lists some of the key AngularJS template features with their
### 绑定/插值表达式
<code-example hideCopy>
Your favorite hero is: {{vm.favoriteHero}}
</code-example>
In AngularJS, an expression in curly braces denotes one-way binding.
@ -118,9 +116,7 @@ The following table lists some of the key AngularJS template features with their
### 过滤器
<code-example hideCopy>
&lt;td>{{movie.title | uppercase}}&lt;/td>
</code-example>
To filter output in AngularJS templates, use the pipe character (|) and one or more filters.
@ -165,11 +161,9 @@ The following table lists some of the key AngularJS template features with their
### 局部变量
<code-example hideCopy format="">
&lt;tr ng-repeat="movie in vm.movies">
&lt;td>{{movie.title}}&lt;/td>
&lt;/tr>
</code-example>
Here, `movie` is a user-defined local variable.
@ -246,9 +240,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-app
<code-example hideCopy>
&lt;body ng-app="movieHunter">
</code-example>
The application startup process is called **bootstrapping**.
@ -295,11 +287,9 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-class
<code-example hideCopy format="">
&lt;div ng-class="{active: isActive}">
&lt;div ng-class="{active: isActive,
shazam: isImportant}">
</code-example>
In AngularJS, the `ng-class` directive includes/excludes CSS classes
@ -361,10 +351,8 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-click
<code-example hideCopy format="">
&lt;button ng-click="vm.toggleImage()">
&lt;button ng-click="vm.toggleImage($event)">
</code-example>
In AngularJS, the `ng-click` directive allows you to specify custom behavior when an element is clicked.
@ -433,9 +421,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-controller
<code-example hideCopy format="">
&lt;div ng-controller="MovieListCtrl as vm">
</code-example>
In AngularJS, the `ng-controller` directive attaches a controller to the view.
@ -506,9 +492,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-href
<code-example hideCopy format="">
&lt;a ng-href="{{ angularDocsUrl }}">Angular Docs&lt;/a>
</code-example>
The `ng-href` directive allows AngularJS to preprocess the `href` property so that it
@ -522,9 +506,7 @@ AngularJS 为模板提供了七十多个内置指令。
在 AngularJS 中,`ng-href` 通常用来作为导航的一部分,激活一个路由。
<code-example hideCopy format="">
&lt;a ng-href="#{{ moviesHash }}">Movies&lt;/a>
</code-example>
Routing is handled differently in Angular.
@ -574,9 +556,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-if
<code-example hideCopy format="">
&lt;table ng-if="movies.length">
</code-example>
In AngularJS, the `ng-if` directive removes or recreates a portion of the DOM,
@ -623,9 +603,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-model
<code-example hideCopy format="">
&lt;input ng-model="vm.favoriteHero"/>
</code-example>
In AngularJS, the `ng-model` directive binds a form control to a property in the controller associated with the template.
@ -665,9 +643,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-repeat
<code-example hideCopy format="">
&lt;tr ng-repeat="movie in vm.movies">
</code-example>
In AngularJS, the `ng-repeat` directive repeats the associated DOM element
@ -719,11 +695,9 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-show
<code-example hideCopy format="">
&lt;h3 ng-show="vm.favoriteHero">
Your favorite hero is: {{vm.favoriteHero}}
&lt;/h3>
</code-example>
In AngularJS, the `ng-show` directive shows or hides the associated DOM element, based on
@ -776,9 +750,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-src
<code-example hideCopy format="">
&lt;img ng-src="{{movie.imageurl}}">
</code-example>
The `ng-src` directive allows AngularJS to preprocess the `src` property so that it
@ -819,9 +791,7 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-style
<code-example hideCopy format="">
&lt;div ng-style="{color: colorPreference}">
</code-example>
In AngularJS, the `ng-style` directive sets a CSS style on an HTML element
@ -877,7 +847,6 @@ AngularJS 为模板提供了七十多个内置指令。
### ng-switch
<code-example hideCopy format="">
&lt;div ng-switch="vm.favoriteHero &&
vm.checkMovieHero(vm.favoriteHero)">
&lt;div ng-switch-when="true">
@ -890,7 +859,6 @@ AngularJS 为模板提供了七十多个内置指令。
Please enter your favorite hero.
&lt;/div>
&lt;/div>
</code-example>
In AngularJS, the `ng-switch` directive swaps the contents of
@ -996,9 +964,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### currency
<code-example hideCopy>
&lt;td>{{movie.price | currency}}&lt;/td>
</code-example>
Formats a number as currency.
@ -1028,9 +994,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### date
<code-example hideCopy>
&lt;td>{{movie.releaseDate | date}}&lt;/td>
</code-example>
Formats a date to a string based on the requested format.
@ -1060,9 +1024,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### filter
<code-example hideCopy>
&lt;tr ng-repeat="movie in movieList | filter: {title:listFilter}">
</code-example>
Selects a subset of items from the defined collection, based on the filter criteria.
@ -1094,9 +1056,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### json
<code-example hideCopy>
&lt;pre>{{movie | json}}&lt;/pre>
</code-example>
Converts a JavaScript object into a JSON string. This is useful for debugging.
@ -1126,9 +1086,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### limitTo
<code-example hideCopy>
&lt;tr ng-repeat="movie in movieList | limitTo:2:0">
</code-example>
Selects up to the first parameter (2) number of items from the collection
@ -1164,9 +1122,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### lowercase
<code-example hideCopy>
&lt;div>{{movie.title | lowercase}}&lt;/div>
</code-example>
Converts the string to lowercase.
@ -1196,9 +1152,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### number
<code-example hideCopy>
&lt;td>{{movie.starRating | number}}&lt;/td>
</code-example>
Formats a number as text.
@ -1236,9 +1190,7 @@ AngularJS 中的很多内置过滤器在 Angular 中都有对应的管道。
### orderBy
<code-example hideCopy>
&lt;tr ng-repeat="movie in movieList | orderBy : 'title'">
</code-example>
Displays the collection in the order specified by the expression.
@ -1322,11 +1274,9 @@ The Angular code is shown using TypeScript.
### IIFE
<code-example hideCopy>
(function () {
...
}());
</code-example>
In AngularJS, an immediately invoked function expression (or IIFE) around controller code
@ -1365,9 +1315,7 @@ The Angular code is shown using TypeScript.
### Angular 模块
<code-example hideCopy>
angular.module("movieHunter", ["ngRoute"]);
</code-example>
In AngularJS, an Angular module keeps track of controllers, services, and other code.
@ -1412,13 +1360,11 @@ The Angular code is shown using TypeScript.
### 控制器注册
<code-example hideCopy>
angular
.module("movieHunter")
.controller("MovieListCtrl",
["movieService",
MovieListCtrl]);
</code-example>
AngularJS has code in each controller that looks up an appropriate Angular module
@ -1470,10 +1416,8 @@ The Angular code is shown using TypeScript.
### 控制器函数
<code-example hideCopy>
function MovieListCtrl(movieService) {
}
</code-example>
In AngularJS, you write the code for the model and methods in a controller function.
@ -1516,11 +1460,9 @@ The Angular code is shown using TypeScript.
### 依赖注入
<code-example hideCopy>
MovieListCtrl.$inject = ['MovieService'];
function MovieListCtrl(movieService) {
}
</code-example>
In AngularJS, you pass in any dependencies as controller function arguments.
@ -1616,9 +1558,7 @@ also encapsulate a style sheet within a specific component.
### Link 标签
<code-example hideCopy>
&lt;link href="styles.css" rel="stylesheet" />
</code-example>
AngularJS, uses a `link` tag in the head section of the `index.html` file

View File

@ -291,10 +291,8 @@ These two common animations have their own aliases:
这两个常见的动画有自己的别名:
<code-example language="typescript">
transition(':enter', [ ... ]); // void => *
transition(':leave', [ ... ]); // * => void
</code-example>
</div>
@ -562,5 +560,4 @@ The callbacks receive an `AnimationEvent` that contains useful properties such a
Those callbacks will fire whether or not an animation is picked up.
无论动画是否实际执行过,那些回调都会触发。

View File

@ -48,10 +48,8 @@ JIT compilation is the default when you run the _build-only_ or the _build-and-s
当你运行 *`build`**`serve`* 这两个 CLI 命令时 JIT 编译是默认选项:
<code-example language="sh" class="code-shell">
ng build
ng serve
</code-example>
{@a compile}
@ -61,10 +59,8 @@ For AOT compilation, append the `--aot` flags to the _build-only_ or the _build-
要进行 AOT 编译只要给这两个 CLI 命令添加 `--aot` 标志就行了:
<code-example language="sh" class="code-shell">
ng build --aot
ng serve --aot
</code-example>
<div class="l-sub-section">
@ -170,7 +166,7 @@ The option is `false` by default.
这个选项告诉编译器不要生成 `.metadata.json` 文件,它默认是 `false`
`.metadata.json` files contain information needed by the template compiler from a `.ts`
`.metadata.json` files contain infomration needed by the template compiler from a `.ts`
file that is not included in the `.d.ts` file produced by the TypeScript compiler. This information contains,
for example, the content of annotations (such as a component's template) which TypeScript
emits to the `.js` file but not to the `.d.ts` file.
@ -195,7 +191,6 @@ include a copy of the information that is in the `.metadata.json` file.
This option tells the template compiler to report an error to the `.metadata.json`
file if `"skipMetadataEmit"` is `false` . This option is `false` by default. This should only be used when `"skipMetadataEmit"` is `false` and `"skipTemplateCodeGen"` is `true`.
<!-- 这里整节都不太确定 -->
这个选项告诉模板编译器如果 `"skipMetadataEmit"``false`,那就把错误信息汇报到 `.metadata.json` 中。
只有当 `"skipMetadataEmit"``false``"skipTemplateCodeGen"``true` 时才应该使用这个选项。
@ -383,21 +378,21 @@ rules.
这是供 `bazel` 构建规则使用的选项,它用于简化 `bazel` 规则跟踪文件依赖的方式。
除了 `bazel` 规则之外不建议使用该选项。
### *enableIvy*
### *enableIvy*
Tells the compiler to generate definitions using the Render3 style code generation. This option defaults to `false`.
Tells the compiler to generate definitions using the Render3 style code generation. This option defaults to `false`.
告诉编译器使用 Render3 风格的代码生成器来来生成各种定义。
告诉编译器使用 Render3 风格的代码生成器来来生成各种定义。
该选项默认为 `false`
Not all features are supported with this option enabled. It is only supported
for experimentation and testing of Render3 style code generation.
Not all features are supported with this option enabled. It is only supported
for experimentation and testing of Render3 style code generation.
当开启该选项时,有些特性不受支持。它仅仅用来为试验和测试 Render3 风格的代码生成提供支持。
当开启该选项时,有些特性不受支持。它仅仅用来为试验和测试 Render3 风格的代码生成提供支持。
*Note*: Is it not recommended to use this option as it is not yet feature complete with the Render2 code generation.
*Note*: Is it not recommended to use this option as it is not yet feature complete with the Render2 code generation.
*注意*:不建议使用该选项,因为它在使用 Render2 的代码生成器时还缺少一些特性。
*注意*:不建议使用该选项,因为它在使用 Render2 的代码生成器时还缺少一些特性。
## Angular Metadata and AOT
@ -828,7 +823,7 @@ The compiler only supports metadata for these Angular decorators.
编译器只支持下列 Angular 装饰器的元数据。
<t>Decorator<t><t>装饰器</t> | <t>Module</t><t>所在模块</t>
<t>Decorator</t><t>装饰器</t> | <t>Module</t><t>所在模块</t>
------------------|--------------
`Attribute` | `@angular/core`
`Component` | `@angular/core`
@ -982,18 +977,18 @@ The following are metadata errors you may encounter, with explanations and sugge
你可能遇到一些元数据错误,下面是对它们的解释和纠正建议。
[Expression form not supported <t>【不支持此表达式格式】</t>](#expression-form-not-supported)<br>
[Reference to a local (non-exported) symbol<t>【引用了局部(未导出的)符号】</t>](#reference-to-a-local-symbol)<br>
[Only initialized variables and constants<t>【只允许初始化过的变量和常量】</t>](#only-initialized-variables)<br>
[Reference to a non-exported class<t>【引用了未导出的类】</t>](#reference-to-a-non-exported-class)<br>
[Reference to a non-exported function<t>【引用了未导出的函数】</t>](#reference-to-a-non-exported-function)<br>
[Function calls are not supported<t>【不支持函数调用】</t>](#function-calls-not-supported)<br>
[Destructured variable or constant not supported<t>【不支持解构变量或常量】</t>](#destructured-variable-not-supported)<br>
[Could not resolve type<t>【不能解析此类型】</t>](#could-not-resolve-type)<br>
[Name expected<t>【期待是名字】</t>](#name-expected)<br>
[Unsupported enum member name<t>【不支持的枚举成员名】</t>](#unsupported-enum-member-name)<br>
[Tagged template expressions are not supported<t>【不支持带标签函数的模板表达式】</t>](#tagged-template-expressions-not-supported)<br>
[Symbol reference expected<t>【期待是符号引用】</t>](#symbol-reference-expected)<br>
[<t>Expression form not supported</t><t>【不支持此表达式格式】</t>](#expression-form-not-supported)<br>
[<t>Reference to a local (non-exported) symbol</t><t>【引用了局部(未导出的)符号】</t>](#reference-to-a-local-symbol)<br>
[<t>Only initialized variables and constants</t><t>【只允许初始化过的变量和常量】</t>](#only-initialized-variables)<br>
[<t>Reference to a non-exported class</t><t>【引用了未导出的类】</t>](#reference-to-a-non-exported-class)<br>
[<t>Reference to a non-exported function</t><t>【引用了未导出的函数】</t>](#reference-to-a-non-exported-function)<br>
[<t>Function calls are not supported</t><t>【不支持函数调用】</t>](#function-calls-not-supported)<br>
[<t>Destructured variable or constant not supported</t><t>【不支持解构变量或常量】</t>](#destructured-variable-not-supported)<br>
[<t>Could not resolve type</t><t>【不能解析此类型】</t>](#could-not-resolve-type)<br>
[<t>Name expected</t><t>【期待是名字】</t>](#name-expected)<br>
[<t>Unsupported enum member name</t><t>【不支持的枚举成员名】</t>](#unsupported-enum-member-name)<br>
[<t>Tagged template expressions are not supported</t><t>【不支持带标签函数的模板表达式】</t>](#tagged-template-expressions-not-supported)<br>
[<t>Symbol reference expected</t><t>【期待是符号引用】</t>](#symbol-reference-expected)<br>
<hr>
@ -1383,7 +1378,6 @@ To correct this error, export a function from the module and refer to the functi
要改正这个问题,就要从模块中导出这个函数,并改成在服务提供商的 `useFactory` 中引用该函数。
<code-example linenums="false">
// CORRECTED
import { calculateValue } from './utilities';
@ -1399,7 +1393,6 @@ export function someValueFactory() {
{ provide: SomeValue, useFactory: someValueFactory }
]
...
</code-example>
<hr>
@ -1425,7 +1418,6 @@ For example, you cannot write something like this:
比如,你不能这么写:
<code-example linenums="false">
// ERROR
import { configuration } from './configuration';
@ -1437,7 +1429,6 @@ const {foo, bar} = configuration;
{provide: Bar, useValue: bar},
]
...
</code-example>
To correct this error, refer to non-destructured values.
@ -1445,7 +1436,6 @@ To correct this error, refer to non-destructured values.
要纠正这个错误,就要引用非解构方式的变量。
<code-example linenums="false">
// CORRECTED
import { configuration } from './configuration';
...
@ -1454,7 +1444,6 @@ import { configuration } from './configuration';
{provide: Bar, useValue: configuration.bar},
]
...
</code-example>
<hr>
@ -1528,7 +1517,6 @@ Here's an illustrative example.
下面的例子说明了这一点。
<code-example linenums="false">
// CORRECTED
import { Inject } from '@angular/core';
@ -1544,7 +1532,6 @@ export function _window() { return window; }
export class MyComponent {
constructor (@Inject(WINDOW) private win: Window) { ... }
}
</code-example>
The `Window` type in the constructor is no longer a problem for the compiler because it
@ -1557,7 +1544,6 @@ Angular does something similar with the `DOCUMENT` token so you can inject the b
Angular 也用 `DOCUMENT` 令牌做了类似的事情,所以你也可以注入浏览器的 `document` 对象(或它的一个抽象层,取决于该应用运行在哪个平台)。
<code-example linenums="false">
import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@ -1565,7 +1551,6 @@ import { DOCUMENT } from '@angular/platform-browser';
export class MyComponent {
constructor (@Inject(DOCUMENT) private doc: Document) { ... }
}
</code-example>
<hr>
@ -1613,7 +1598,6 @@ The compiler can understand simple enum values but not complex values such as th
编译器可以理解简单的枚举值,但不能理解复杂的,比如从那些计算属性中派生出来的。
<code-example linenums="false">
// ERROR
enum Colors {
Red = 1,
@ -1628,7 +1612,6 @@ enum Colors {
{ provide: StrongColor, useValue: Colors.Blue } // bad
]
...
</code-example>
Avoid referring to enums with complicated initializers or computed properties.

View File

@ -4,9 +4,7 @@
</div>
<header class="api-header">
<h1><label class="api-status-label experimental">experimental</label><label class="api-type-label class">class</label>Class Name</h1>
</header>
<header class="api-header"><h1><label class="api-status-label experimental">experimental</label><label class="api-type-label class">class</label>Class Name</h1></header>
<div class="page-actions">
@ -84,13 +82,13 @@
</li>
</ul>
</section>
<section>
<h2>Constructor</h2>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
@ -103,7 +101,6 @@
<table class="is-full-width list-table">
<thead>
<tr>
<th>
@ -131,10 +128,8 @@
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
@ -156,7 +151,6 @@
</td>
</tr>
<tr>
<td>
@ -180,7 +174,6 @@
</td>
</tr>
<tr>
<td>
@ -204,7 +197,6 @@
</td>
</tr>
</tbody>
</table>
</section>
@ -214,7 +206,6 @@
<table class="is-full-width item-table">
<thead>
<tr>
<th>
@ -224,10 +215,8 @@
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
@ -241,12 +230,10 @@
</td>
</tr>
</tbody>
</table>
<table class="is-full-width api-method item-table">
<thead>
<tr>
<th>
@ -256,10 +243,8 @@
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
@ -271,11 +256,10 @@
<h5>Declaration</h5>
<code-example language="ts" hidecopy="true" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-ts">
<code class="animated fadeIn"><span class="kwd">class</span><span class="pln"> </span><a href="api/animations/AnimationBuilder" class="code-anchor"><span class="typ">AnimationBuilder</span></a><span class="pln"> </span><span class="pun">{</span><span class="pln"></span><a class="code-anchor" href="api/animations/AnimationBuilder#build"><span class="pln">build</span><span class="pun">(</span><span class="pln">animation</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AnimationMetadata</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">AnimationMetadata</span><span class="pun">[]):</span><span class="pln"> </span><span class="typ">AnimationFactory</span></a><span class="pln"></span><span class="pun">}</span></code></pre>
</aio-code>
</aio-code>
</code-example>
<h6>Parameters</h6>
@ -296,13 +280,10 @@
<table class="is-full-width">
<tbody>
<tr>
<td>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
@ -318,13 +299,11 @@
</td>
</tr>
<tr>
<td>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
@ -340,7 +319,6 @@
</td>
</tr>
</tbody>
</table>
@ -351,9 +329,7 @@
<p>Bacon ipsum dolor amet pork belly capicola sirloin venison alcatra ground round ham hock jowl turkey picanha bresaola pancetta brisket chicken fatback. Burgdoggen kevin salami jowl shoulder jerky leberkas meatball. Ham hock picanha burgdoggen pork belly rump bacon cupim. Bacon kielbasa sirloin shank strip steak ground round. Bresaola cow salami meatloaf pork chop leberkas flank turducken biltong meatball chuck pork tri-tip chicken. Ribeye corned beef shoulder, meatloaf strip steak jerky porchetta capicola alcatra ham.</p>
</td>
</tr>
</tbody>
</table>
</section>
@ -364,7 +340,6 @@
<p>Intro description text about what the example is and how it can be used.</p>
<code-example hidecopy="true" class="no-box api-heading" ng-version="5.2.0">
<aio-code class="simple-code"><pre class="prettyprint lang-">
<code class="animated fadeIn"><span class="kwd">constructor</span><span class="pun">(</span><span class="pln">element</span><span class="pun">:</span><span class="pln"> any</span><span class="pun">,</span><span class="pln"> keyframes</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">[</span><span class="pln">key</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">]:</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">

View File

@ -10,6 +10,8 @@ While a small application might have only one NgModule, most apps have many more
## NgModule metadata
## `@NgModule` 元数据
An NgModule is defined as a class decorated with `@NgModule`. The `@NgModule` decorator is a function that takes a single metadata object, whose properties describe the module. The most important properties are as follows.
* `declarations`&mdash;The [components](guide/architecture-components), _directives_, and _pipes_ that belong to this NgModule.

View File

@ -1,4 +1,4 @@
# Architecture Overview
# Architecture overview
# 架构概览
@ -122,6 +122,8 @@ To define navigation rules, you associate *navigation paths* with your component
## What's next
## 接下来呢?
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
<figure>

View File

@ -83,9 +83,7 @@ Create the directive class file in a terminal window with this CLI command.
在命令行窗口下用 CLI 命令创建指令类文件。
<code-example language="sh" class="code-shell">
ng generate directive highlight
</code-example>
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file (`.../spec.ts`, and _declares_ the directive class in the root `AppModule`.
@ -197,9 +195,7 @@ Now run the application to see the `HighlightDirective` in action.
运行这个应用以查看 `HighlightDirective` 的实际效果。
<code-example language="sh" class="code-shell">
ng serve
</code-example>
To summarize, Angular found the `appHighlight` attribute on the **host** `<p>` element.
@ -531,14 +527,12 @@ The final source code follows:
最终的源码如下:
<code-tabs>
<code-pane title="app/app.component.ts" path="attribute-directives/src/app/app.component.ts"></code-pane>
<code-pane title="app/app.component.html" path="attribute-directives/src/app/app.component.html"></code-pane>
<code-pane title="app/highlight.directive.ts" path="attribute-directives/src/app/highlight.directive.ts"></code-pane>
<code-pane title="app/app.module.ts" path="attribute-directives/src/app/app.module.ts"></code-pane>
<code-pane title="main.ts" path="attribute-directives/src/main.ts"></code-pane>
<code-pane title="index.html" path="attribute-directives/src/index.html"></code-pane>
</code-tabs>
You can also experience and download the <live-example title="Attribute Directive example"></live-example>.

View File

@ -12,7 +12,7 @@ A basic understanding of the following:
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
[JavaScript 模块与 NgModules](guide/ngmodule-vs-jsmodule).
[JavaScript 模块与 NgModules](guide/ngmodule-vs-jsmodule)
<hr />
@ -176,7 +176,6 @@ The following example, named `ItemDirective` is the default directive structure
下面的例子中,`item.directive.ts` 中的 `ItemDirective` 是 CLI 自动生成的默认指令结构。
<code-example path="bootstrapping/src/app/item.directive.ts" region="directive" title="src/app/item.directive.ts" linenums="false">
</code-example>
The key point here is that you have to export it so you can import it elsewhere. Next, import it
@ -185,7 +184,6 @@ into the NgModule, in this example `app.module.ts`, with a JavaScript import sta
重点在于你要先在这里导出它才能在别处导入它。接下来,使用 JavaScript 的 `import` 语句把它导入到 NgModule 中(这里是 `app.module.ts`)。
<code-example path="bootstrapping/src/app/app.module.ts" region="directive-import" title="src/app/app.module.ts" linenums="false">
</code-example>
And in the same file, add it to the `@NgModule` `declarations` array:
@ -193,7 +191,6 @@ And in the same file, add it to the `@NgModule` `declarations` array:
同样在这个文件中,把它添加到 `@NgModule``declarations` 数组中:
<code-example path="bootstrapping/src/app/app.module.ts" region="declarations" title="src/app/app.module.ts" linenums="false">
</code-example>
Now you could use your `ItemDirective` in a component. This example uses `AppModule`, but you'd do it the same way for a feature module. For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). You'd also use the same technique for [pipes](guide/pipes) and components.

View File

@ -81,7 +81,6 @@ Angular 支持大多数常用浏览器,包括下列版本:
</td>
</tr>
<tr>
<td>
@ -97,9 +96,7 @@ Angular 支持大多数常用浏览器,包括下列版本:
</td>
</tr>
<tr>
<tr>
<td>
@ -115,7 +112,6 @@ Angular 支持大多数常用浏览器,包括下列版本:
</td>
</tr>
<tr>
<td>
@ -133,7 +129,6 @@ Angular 支持大多数常用浏览器,包括下列版本:
</td>
</tr>
<tr>
<td>
@ -151,7 +146,6 @@ Angular 支持大多数常用浏览器,包括下列版本:
</td>
</tr>
<tr>
<td>
@ -239,7 +233,6 @@ For example, [if you need the web animations polyfill](http://caniuse.com/#feat=
# it isn't a strict requirement of Angular anymore (more below)
npm install --save web-animations-js
</code-example>
Then open the `polyfills.ts` file and un-comment the corresponding `import` statement as in the following example:
@ -247,7 +240,6 @@ Then open the `polyfills.ts` file and un-comment the corresponding `import` stat
然后打开 `polyfills.ts` 文件,并反注释对应的 `import` 语句,就像这样:
<code-example title="src/polyfills.ts">
/**
* Required to support Web Animations `@angular/platform-browser/animations`.
@ -255,7 +247,6 @@ Then open the `polyfills.ts` file and un-comment the corresponding `import` stat
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
**/
import 'web-animations-js'; // Run `npm install --save web-animations-js`.
</code-example>
If you can't find the polyfill you want in `polyfills.ts`,
@ -799,7 +790,6 @@ If you are not using the CLI, you should add your polyfill scripts directly to t
如果你不使用 CLI就要直接把腻子脚本添加到宿主页`index.html`)中,就像这样:
<code-example title="src/index.html">
&lt;!-- pre-zone polyfills -->
&lt;script src="node_modules/core-js/client/shim.min.js">&lt;/script>
&lt;script src="node_modules/web-animations-js/web-animations.min.js">&lt;/script>
@ -828,5 +818,4 @@ If you are not using the CLI, you should add your polyfill scripts directly to t
&lt;script src="node_modules/zone.js/dist/zone.js">&lt;/script>
&lt;!-- application polyfills -->
</code-example>

View File

@ -431,5 +431,4 @@ modules with SystemJS as the samples currently do.
The [Lifecycle Hooks](guide/lifecycle-hooks) guide is shorter, simpler, and
draws more attention to the order in which Angular calls the hooks.
[生命周期钩子](guide/lifecycle-hooks)章现在更加简短,并且对强调了 Angular 是以什么顺序来调用钩子方法的。

View File

@ -18,13 +18,11 @@
<th>
<p><code>import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -42,7 +40,6 @@
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -57,13 +54,11 @@
<th>
<p><code>import { NgModule } from '@angular/core';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -162,7 +157,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -181,7 +175,6 @@ is available to <code>declarations</code> of this module.</p>
</th>
</tr>
<tr>
<td>
@ -410,7 +403,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -427,13 +419,11 @@ is available to <code>declarations</code> of this module.</p>
<th>
<p><code>import { CommonModule } from '@angular/common';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -499,7 +489,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
<tr>
<td>
@ -517,7 +506,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -534,13 +522,11 @@ is available to <code>declarations</code> of this module.</p>
<th>
<p><code>import { FormsModule } from '@angular/forms';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -558,7 +544,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -575,13 +560,11 @@ is available to <code>declarations</code> of this module.</p>
<th>
<p><code>import { Directive, ... } from '@angular/core';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -641,16 +624,13 @@ is available to <code>declarations</code> of this module.</p>
<td>
<p>Declares that a class has dependencies that should be injected into the constructor when the dependency injector is creating an instance of this class.
</p>
<p>声明某个类具有一些依赖。当依赖注入器要创建这个类的实例时,应该把这些依赖注入到它的构造函数中。</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -667,13 +647,11 @@ is available to <code>declarations</code> of this module.</p>
<th>
<p><code>@Directive({ property1: value1, ... })</code>
</p>
</th>
</tr>
<tr>
<td>
@ -712,7 +690,6 @@ is available to <code>declarations</code> of this module.</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -728,7 +705,8 @@ is available to <code>declarations</code> of this module.</p>
<th>
<p><code>@Component</code> extends <code>@Directive</code>,
<p>
<code>@Component</code> extends <code>@Directive</code>,
so the <code>@Directive</code> configuration applies to components as well</p>
<p><code>@Component</code> 继承自 <code>@Directive</code>
@ -737,7 +715,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</th>
</tr>
<tr>
<td>
@ -803,7 +780,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -820,13 +796,11 @@ so the <code>@Directive</code> configuration applies to components as well</p>
<th>
<p><code>import { Input, ... } from '@angular/core';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -957,7 +931,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -974,15 +947,13 @@ so the <code>@Directive</code> configuration applies to components as well</p>
<th>
<p>(implemented as class methods)
</p>
<p>由类的方法实现。</p>
<p>由类的方法实现。</p>
</th>
</tr>
<tr>
<td>
@ -1128,7 +1099,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -1147,7 +1117,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</th>
</tr>
<tr>
<td>
@ -1197,7 +1166,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</td>
</tr>
</tbody></table>
<table class="is-full-width is-fixed-layout">
@ -1214,13 +1182,11 @@ so the <code>@Directive</code> configuration applies to components as well</p>
<th>
<p><code>import { Routes, RouterModule, ... } from '@angular/router';</code>
</p>
</th>
</tr>
<tr>
<td>
@ -1366,7 +1332,6 @@ so the <code>@Directive</code> configuration applies to components as well</p>
</td>
</tr>
</tbody></table>
</div>

View File

@ -39,19 +39,17 @@ Observables are often compared to promises. Here are some key differences:
### 创建与订阅
* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
* Observables are not executed until a consumer subcribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
在有消费者订阅之前,可观察对象不会执行。`subscribe()` 会执行一次定义好的行为,并且可以再次调用它。每次订阅都是单独计算的。重新订阅会导致重新计算这些值。
<code-example hideCopy>
// declare a publishing operation
new Observable((observer) => { subscriber_fn });
// initiate execution
observable.subscribe(() => {
// observer handles notifications
});
</code-example>
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
@ -59,14 +57,12 @@ observable.subscribe(() => {
承诺会立即执行,并且只执行一次。当承诺创建时,会立即计算出结果。没有办法重新做一次。所有的 `then` 语句(订阅)都会共享同一次计算。
<code-example hideCopy>
// initiate execution
new Promise((resolve, reject) => { executer_fn });
// handle return value
promise.then((value) => {
// handle result here
});
</code-example>
### Chaining
@ -94,10 +90,8 @@ promise.then((value) => {
可观察对象的订阅是可取消的。取消订阅会移除监听器,使其不再接受将来的值,并通知订阅者函数取消正在进行的工作。
<code-example hideCopy>
const sub = obs.subscribe(...);
sub.unsubscribe();
</code-example>
* Promises are not cancellable.
@ -113,11 +107,9 @@ sub.unsubscribe();
可观察对象的错误处理是交给订阅者的错误处理器的,并且该订阅者会自动取消对这个可观察对象的订阅。
<code-example hideCopy>
obs.subscribe(() => {
throw Error('my error');
});
</code-example>
* Promises push errors to the child promises.
@ -125,11 +117,9 @@ obs.subscribe(() => {
承诺会把错误推给其子承诺。
<code-example hideCopy>
promise.then(() => {
throw Error('my error');
});
</code-example>
### Cheat sheet
@ -141,7 +131,6 @@ The following code snippets illustrate how the same kind of operation is defined
下列代码片段揭示了同样的操作要如何分别使用可观察对象和承诺进行实现。
<table>
<tr>
<th>
@ -169,7 +158,6 @@ The following code snippets illustrate how the same kind of operation is defined
</th>
</tr>
<tr>
<td>
@ -197,7 +185,6 @@ The following code snippets illustrate how the same kind of operation is defined
</td>
</tr>
<tr>
<td>
@ -221,7 +208,6 @@ The following code snippets illustrate how the same kind of operation is defined
</td>
</tr>
<tr>
<td>
@ -249,7 +235,6 @@ The following code snippets illustrate how the same kind of operation is defined
</td>
</tr>
<tr>
<td>
@ -275,7 +260,6 @@ The following code snippets illustrate how the same kind of operation is defined
</td>
</tr>
</table>
## Observables compared to events API
@ -295,9 +279,12 @@ Here are some code samples that illustrate how the same kind of operation is def
下列代码片段揭示了同样的操作要如何分别使用可观察对象和事件 API 进行实现。
<table>
<tr>
<th>
</th>
<th>
Observable
@ -315,7 +302,6 @@ Here are some code samples that illustrate how the same kind of operation is def
</th>
</tr>
<tr>
<td>
@ -353,7 +339,6 @@ button.removeEventListener(click, handler);
</td>
</tr>
<tr>
<td>
@ -381,7 +366,6 @@ button.removeEventListener(click, handler);
</td>
</tr>
<tr>
<td>
@ -418,7 +402,6 @@ button.removeEventListener(click, handler);
</td>
</tr>
</table>
## Observables compared to arrays
@ -431,9 +414,12 @@ An observable produces values over time. An array is created as a static set of
在下列例子中,➞ 符号表示异步传递值。
<table>
<tr>
<th>
</th>
<th>
Observable
@ -451,7 +437,6 @@ An observable produces values over time. An array is created as a static set of
</th>
</tr>
<tr>
<td>
@ -465,6 +450,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs: ➞1➞2➞3➞5➞7</pre>
<pre>obsB: ➞'a'➞'b'➞'c'</pre>
</td>
@ -472,12 +458,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr: [1, 2, 3, 5, 7]</pre>
<pre>arrB: ['a', 'b', 'c']</pre>
</td>
</tr>
<tr>
<td>
@ -489,6 +475,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.concat(obsB)</pre>
<pre>➞1➞2➞3➞5➞7➞'a'➞'b'➞'c'</pre>
</td>
@ -496,12 +483,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.concat(arrB)</pre>
<pre>[1,2,3,5,7,'a','b','c']</pre>
</td>
</tr>
<tr>
<td>
@ -513,6 +500,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.filter((v) => v>3)</pre>
<pre>➞5➞7</pre>
</td>
@ -520,12 +508,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.filter((v) => v>3)</pre>
<pre>[5, 7]</pre>
</td>
</tr>
<tr>
<td>
@ -537,6 +525,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.find((v) => v>3)</pre>
<pre>➞5</pre>
</td>
@ -544,12 +533,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.find((v) => v>10)</pre>
<pre>5</pre>
</td>
</tr>
<tr>
<td>
@ -561,6 +550,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.findIndex((v) => v>3)</pre>
<pre>➞3</pre>
</td>
@ -568,12 +558,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.findIndex((v) => v>3)</pre>
<pre>3</pre>
</td>
</tr>
<tr>
<td>
@ -609,7 +599,6 @@ An observable produces values over time. An array is created as a static set of
</td>
</tr>
<tr>
<td>
@ -621,6 +610,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.map((v) => -v)</pre>
<pre>➞-1➞-2➞-3➞-5➞-7</pre>
</td>
@ -628,12 +618,12 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.map((v) => -v)</pre>
<pre>[-1, -2, -3, -5, -7]</pre>
</td>
</tr>
<tr>
<td>
@ -645,6 +635,7 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>obs.scan((s,v)=> s+v, 0)</pre>
<pre>➞1➞3➞6➞11➞18</pre>
</td>
@ -652,10 +643,10 @@ An observable produces values over time. An array is created as a static set of
<td>
<pre>arr.reduce((s,v) => s+v, 0)</pre>
<pre>18</pre>
</td>
</tr>
</table>

View File

@ -525,5 +525,4 @@ and verify that the history meets expectations:
[Back to top](guide/component-interaction#top)
[回到顶部](guide/component-interaction#top)

View File

@ -20,7 +20,7 @@ This page describes how to load and apply these component styles.
You can run the <live-example></live-example> in Stackblitz and download the code from there.
你可以运行<live-example></live-example>在 Stackblitz 中试用并下载本页的代码。
你可以运行<live-example></live-example>在 Stackblitz 中试用并下载本页的代码。
## Using component styles
@ -42,7 +42,6 @@ Usually you give it one string, as in the following example:
通常你只给它一个字符串就行了,如同下例:
<code-example path="component-styles/src/app/hero-app.component.ts" title="src/app/hero-app.component.ts" linenums="false">
</code-example>
## Style scope
@ -116,7 +115,6 @@ targeting elements *inside* the component's template).
使用 `:host` 伪类选择器,用来选择组件*宿主*元素中的元素(相对于组件模板*内部*的元素)。
<code-example path="component-styles/src/app/hero-details.component.css" region="host" title="src/app/hero-details.component.css" linenums="false">
</code-example>
The `:host` selector is the only way to target the host element. You can't reach
@ -136,7 +134,6 @@ The next example targets the host element again, but only when it also has the `
下一个例子再次把宿主元素作为目标,但是只有当它同时带有 `active` CSS 类的时候才会生效。
<code-example path="component-styles/src/app/hero-details.component.css" region="hostfunction" title="src/app/hero-details.component.css" linenums="false">
</code-example>
### :host-context
@ -163,7 +160,6 @@ if some ancestor element has the CSS class `theme-light`.
在下面的例子中,只有当某个祖先元素有 CSS 类 `theme-light` 时,才会把 `background-color` 样式应用到组件*内部*的所有 `<h2>` 元素中。
<code-example path="component-styles/src/app/hero-details.component.css" region="hostcontext" title="src/app/hero-details.component.css" linenums="false">
</code-example>
### (deprecated) `/deep/`, `>>>`, and `::ng-deep`
@ -257,7 +253,6 @@ Each string in the array defines some CSS for this component.
这个数组中的每一个字符串(通常也只有一个)定义一份 CSS。
<code-example path="component-styles/src/app/hero-app.component.ts" title="src/app/hero-app.component.ts (CSS inline)">
</code-example>
<div class="alert is-critical">
@ -275,9 +270,7 @@ The CLI defines an empty `styles` array when you create the component with the `
当使用 `--inline-styles` 标识创建组件时CLI 就会定义一个空的 `styles` 数组
<code-example language="sh" class="code-shell">
ng generate component hero-app --inline-style
</code-example>
### Style files in component metadata
@ -290,10 +283,8 @@ to a component's `@Component` decorator:
你可以通过把外部 CSS 文件添加到 `@Component``styleUrls` 属性中来加载外部样式。
<code-tabs>
<code-pane title="src/app/hero-app.component.ts (CSS in file)" path="component-styles/src/app/hero-app.component.1.ts"></code-pane>
<code-pane title="src/app/hero-app.component.css" path="component-styles/src/app/hero-app.component.css"></code-pane>
</code-tabs>
<div class="alert is-critical">
@ -319,9 +310,7 @@ The CLI creates an empty styles file for you by default and references that file
CLI 会默认为你创建一个空白的样式表文件,并且在所生成组件的 `styleUrls` 中引用该文件。
<code-example language="sh" class="code-shell">
ng generate component hero-app
</code-example>
### Template inline styles
@ -334,7 +323,6 @@ inside `<style>` tags.
你也可以在组件的 HTML 模板中嵌入 `<style>` 标签。
<code-example path="component-styles/src/app/hero-controls.component.ts" region="inlinestyles" title="src/app/hero-controls.component.ts">
</code-example>
### Template link tags
@ -346,7 +334,6 @@ You can also write `<link>` tags into the component's HTML template.
你也可以在组件的 HTML 模板中写 `<link>` 标签。
<code-example path="component-styles/src/app/hero-team.component.ts" region="stylelink" title="src/app/hero-team.component.ts">
</code-example>
<div class="alert is-critical">
@ -378,7 +365,6 @@ In this case, the URL is relative to the CSS file into which you're importing.
在*这种*情况下URL 是相对于你正在导入的 CSS 文件的。
<code-example path="component-styles/src/app/hero-details.component.css" region="import" title="src/app/hero-details.component.css (excerpt)">
</code-example>
### External and global style files
@ -407,14 +393,12 @@ you can write style files in [sass](http://sass-lang.com/), [less](http://lesscs
如果使用 CLI 进行构建,那么你可以用 [sass](http://sass-lang.com/)、[less](http://lesscss.org/) 或 [stylus](http://stylus-lang.com/) 来编写样式,并使用相应的扩展名(`.scss`、`.less`、`.styl`)把它们指定到 `@Component.styleUrls` 元数据中。例子如下:
<code-example>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
...
</code-example>
The CLI build process runs the pertinent CSS preprocessor.
@ -486,7 +470,6 @@ To set the components encapsulation mode, use the `encapsulation` property in th
通过组件元数据中的 `encapsulation` 属性来设置组件封装模式:
<code-example path="component-styles/src/app/quest-summary.component.ts" region="encapsulation.native" title="src/app/quest-summary.component.ts" linenums="false">
</code-example>
`Native` view encapsulation only works on browsers that have native support
@ -516,7 +499,6 @@ attached to it:
在启用了仿真模式的 Angular 应用的 DOM 树中,每个 DOM 元素都被加上了一些额外的属性。
<code-example format="">
&lt;hero-details _nghost-pmm-5>
&lt;h2 _ngcontent-pmm-5>Mister Fantastic&lt;/h2>
&lt;hero-team _ngcontent-pmm-5 _nghost-pmm-6>
@ -549,7 +531,6 @@ by the generated component styles, which are in the `<head>` section of the DOM:
但它们会作为生成的组件样式的目标,就像 DOM 的 `<head>` 中一样:
<code-example format="">
[_nghost-pmm-5] {
display: block;
border: 1px solid black;
@ -559,13 +540,11 @@ by the generated component styles, which are in the `<head>` section of the DOM:
background-color: white;
border: 1px solid #777;
}
</code-example>
These styles are post-processed so that each selector is augmented
with `_nghost` or `_ngcontent` attribute selectors.
These extra selectors enable the scoping rules described in this page.
这些就是那些样式被处理后的结果,每个选择器都被增加了 `_nghost``_ngcontent` 属性选择器。
这些额外的选择器实现了本文所描述的这些作用域规则。

View File

@ -34,7 +34,6 @@ Imagine writing the following code:
要理解为什么依赖注入这么重要,不妨先考虑不使用它的一个例子。想象下列代码:
<code-example path="dependency-injection/src/app/car/car-no-di.ts" region="car" title="src/app/car/car.ts (without DI)">
</code-example>
The `Car` class creates everything it needs inside its constructor.
@ -152,7 +151,6 @@ Now you can create a car by passing the engine and tires to the constructor.
现在,通过往构造函数中传入引擎和轮胎来创建一辆车。
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation" linenums="false">
</code-example>
How cool is that?
@ -195,7 +193,6 @@ during each test:
在每个测试期间,你可以往构造函数中传入 mock 对象,做想让它们做的事:
<code-example path="dependency-injection/src/app/car/car-creations.ts" region="car-ctor-instantiation-with-mocks" linenums="false">
</code-example>
**You just learned what dependency injection is**.
@ -223,7 +220,6 @@ You _could_ write a giant class to do that:
可以写一个巨型类来做这件事:
<code-example path="dependency-injection/src/app/car/car-factory.ts" title="src/app/car/car-factory.ts">
</code-example>
It's not so bad now with only three creation methods.
@ -253,7 +249,6 @@ When you need a `Car`, you simply ask the injector to get it for you and you're
当需要一个 `Car` 时,就简单的找注入器取车就可以了。
<code-example path="dependency-injection/src/app/car/car-injector.ts" region="injector-call" title="src/app/car/car-injector.ts" linenums="false">
</code-example>
Everyone wins. The `Car` knows nothing about creating an `Engine` or `Tires`.

View File

@ -30,7 +30,6 @@ from the [The Tour of Heroes](tutorial/).
先从[《英雄指南》](tutorial/)中*英雄*特性区的一个简化版本开始。
<code-tabs>
<code-pane title="src/app/heroes/heroes.component.ts" path="dependency-injection/src/app/heroes/heroes.component.1.ts"
region="v1">
</code-pane>
@ -60,7 +59,6 @@ defined in a separate `mock-heroes` file.
<code-example title="src/app/heroes/hero-list.component.ts (class)" path="dependency-injection/src/app/heroes/hero-list.component.1.ts"
region="class">
</code-example>
That may suffice in the early stages of development, but it's far from ideal.
@ -85,9 +83,7 @@ The [**Angular CLI**](https://cli.angular.io/) can generate a new `HeroService`
[**Angular CLI**](https://cli.angular.io/) 可以使用下列命令在 `src/app/heroes` 目录下新建一个 `HeroService` 类。
<code-example language="sh" class="code-shell">
ng generate service heroes/hero
</code-example>
That command creates the following `HeroService` skeleton.
@ -95,7 +91,6 @@ That command creates the following `HeroService` skeleton.
这条命令会创建如下的 `HeroService` 骨架代码:
<code-example path="dependency-injection/src/app/heroes/hero.service.0.ts" title="src/app/heroes/hero.service.ts (CLI-generated)">
</code-example>
Assume for now that the [`@Injectable` decorator](#injectable) is an essential ingredient in every Angular service definition.
@ -106,7 +101,6 @@ that returns the same mock data as before.
把该类的其它部分改写为暴露一个返回和以前一样的 mock 数据的 `getHeroes` 方法。
<code-example path="dependency-injection/src/app/heroes/hero.service.1.ts" title="src/app/heroes/hero.service.ts">
</code-example>
Of course, this isn't a real data service.
@ -189,7 +183,6 @@ Here's a revised `HeroesComponent` that registers the `HeroService` in its `prov
下面是修改过的 `HerosComponent`,把 `HeroService` 注册到了它的 `providers` 数组中。
<code-example path="dependency-injection/src/app/heroes/heroes.component.1.ts" title="src/app/heroes/heroes.component.ts" linenums="false">
</code-example>
{@a register-providers-ngmodule}
@ -203,7 +196,6 @@ In the following excerpt, the root `AppModule` registers two providers in its `p
在下面的代码片段中,根模块 `AppModule` 在自己的 `providers` 数组中注册了两个提供商。
<code-example path="dependency-injection/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (providers)" region="providers">
</code-example>
The first entry registers the `UserService` class (_not shown_) under the `UserService` _injection token_.
@ -284,7 +276,7 @@ and is never destroyed so the `HeroService` created for the `HeroComponent` also
在这个范例应用中,`HeroComponent` 会在应用启动时创建,并且它从未销毁,因此,由 `HeroComponent` 创建的 `HeroService` 也同样会活在应用的整个生命周期中。
If you want to restrict `HeroService` access to the `HeroesComponent` and its nested `HeroListComponent`,
If you want to restrict `HeroService` access to the `HeroComponent` and its nested `HeroListComponent`,
providing the `HeroService` in the `HeroComponent` may be a good choice.
如果你要把 `HeroService` 的访问权限定在 `HeroesComponent` 及其嵌套的 `HeroListComponent` 中,那么在 `HeroesComponent` 中提供这个 `HeroService` 就是一个好选择。
@ -319,7 +311,6 @@ Here's the `HeroListComponent` constructor, asking for the `HeroService` to be i
<code-example title="src/app/heroes/hero-list.component (constructor signature)" path="dependency-injection/src/app/heroes/hero-list.component.ts"
region="ctor-signature">
</code-example>
Of course, the `HeroListComponent` should do something with the injected `HeroService`.
@ -329,13 +320,11 @@ Here's the revised component, making use of the injected service, side-by-side w
下面输出修改过的组件,改用注入的服务,与前一个版本对比一下。
<code-tabs>
<code-pane title="hero-list.component (with DI)" path="dependency-injection/src/app/heroes/hero-list.component.2.ts">
</code-pane>
<code-pane title="hero-list.component (without DI)" path="dependency-injection/src/app/heroes/hero-list.component.1.ts">
</code-pane>
</code-tabs>
Notice that the `HeroListComponent` doesn't know where the `HeroService` comes from.
@ -431,7 +420,6 @@ under test:
例如,新建的 `HeroListComponent` 实例使用一个模拟 (mock) 服务,以便可以在测试中操纵它:
<code-example path="dependency-injection/src/app/test.component.ts" region="spec" title="src/app/test.component.ts" linenums="false">
</code-example>
<div class="l-sub-section">
@ -490,7 +478,6 @@ The sample app's `Logger` service is quite simple:
这个范例应用的 `Logger` 服务非常简单:
<code-example path="dependency-injection/src/app/logger.service.ts" title="src/app/logger.service.ts">
</code-example>
If the app didn't provide this `Logger`,
@ -500,9 +487,7 @@ into the `HeroService`.
如果该应用没有提供这个 `Logger` 服务,当 Angular 试图把 `Logger` 注入到 `HeroService` 中时,就会抛出一个异常。
<code-example language="sh" class="code-shell">
ERROR Error: No provider for Logger!
</code-example>
Because a singleton logger service is useful everywhere,
@ -511,7 +496,6 @@ it's provided in the root `AppModule`.
因为 `Logger` 服务的单例应该随处可用,所以要在根模块 `AppModule` 中提供它。
<code-example path="dependency-injection/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (providers)" region="providers-2">
</code-example>
{@a injectable}
@ -619,7 +603,6 @@ The `Logger` class itself is an obvious and natural provider.
`Logger` 类本身是一个显而易见而且自然而然的提供商。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-logger">
</code-example>
But it's not the only way.
@ -651,7 +634,6 @@ Here's the class-provider syntax again.
下面是类提供商的另一种语法。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-logger">
</code-example>
This is actually a shorthand expression for a provider registration
@ -661,7 +643,6 @@ using a _provider_ object literal with two properties:
使用的是一个带有两个属性的*提供商*对象字面量:
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-3" >
</code-example>
The `provide` property holds the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value
@ -691,7 +672,6 @@ to return a `BetterLogger` when something asks for the `Logger`.
下列代码告诉注入器,当有人请求 `Logger` 时,返回 `BetterLogger`
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-4" >
</code-example>
{@a class-provider-dependencies}
@ -709,7 +689,6 @@ which is also injected at the application level.
`UserService` 通常也会在应用级注入。
<code-example path="dependency-injection/src/app/providers.component.ts" region="EvenBetterLogger" linenums="false">
</code-example>
Configure it like `BetterLogger`.
@ -717,7 +696,6 @@ Configure it like `BetterLogger`.
就像之前在 `BetterLogger` 中那样配置它。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-5" linenums="false">
</code-example>
{@a aliased-class-providers}
@ -753,7 +731,6 @@ Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger
不幸的是,如果尝试通过 `useClass` 来把 `OldLogger` 作为 `NewLogger` 的别名,就会导致这样的后果。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6a" linenums="false">
</code-example>
The solution: alias with the `useExisting` option.
@ -761,7 +738,6 @@ The solution: alias with the `useExisting` option.
解决方案:使用 `useExisting` 选项指定别名。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-6b" linenums="false">
</code-example>
{@a value-provider}
@ -775,7 +751,6 @@ Sometimes it's easier to provide a ready-made object rather than ask the injecto
有时,提供一个预先做好的对象会比请求注入器从类中创建它更容易。
<code-example path="dependency-injection/src/app/providers.component.ts" region="silent-logger" linenums="false">
</code-example>
Then you register a provider with the `useValue` option,
@ -784,7 +759,6 @@ which makes this object play the logger role.
于是可以通过 `useValue` 选项来注册提供商,它会让这个对象直接扮演 logger 的角色。
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-7" linenums="false">
</code-example>
See more `useValue` examples in the
@ -843,7 +817,6 @@ Instead, the `HeroService` constructor takes a boolean flag to control display o
`HeroService` 的构造函数带上一个布尔型的标志,来控制是否显示隐藏的英雄。
<code-example path="dependency-injection/src/app/heroes/hero.service.ts" region="internals" title="src/app/heroes/hero.service.ts (excerpt)" linenums="false">
</code-example>
You can inject the `Logger`, but you can't inject the boolean `isAuthorized`.
@ -857,7 +830,6 @@ A factory provider needs a factory function:
工厂提供商需要一个工厂方法:
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="factory" title="src/app/heroes/hero.service.provider.ts (excerpt)" linenums="false">
</code-example>
Although the `HeroService` has no access to the `UserService`, the factory function does.
@ -870,7 +842,6 @@ and let the injector pass them along to the factory function:
同时把 `Logger``UserService` 注入到工厂提供商中,并且让注入器把它们传给工厂方法:
<code-example path="dependency-injection/src/app/heroes/hero.service.provider.ts" region="provider" title="src/app/heroes/hero.service.provider.ts (excerpt)" linenums="false">
</code-example>
<div class="l-sub-section">
@ -938,7 +909,6 @@ Here you get a `HeroService` directly from the injector by supplying the `HeroSe
在下面的代码中,`HeroService` 类型作为令牌,直接从注入器中获取 `HeroService` 实例:
<code-example path="dependency-injection/src/app/injector.component.ts" region="get-hero-service" title="src/app/injector.component.ts" linenums="false">
</code-example>
You have similar good fortune when you write a constructor that requires an injected class-based dependency.
@ -951,7 +921,6 @@ service associated with that `HeroService` class token:
Angular 就会知道把跟 `HeroService` 类令牌关联的服务注入进来:
<code-example path="dependency-injection/src/app/heroes/hero-list.component.ts" region="ctor-signature" title="src/app/heroes/hero-list.component.ts">
</code-example>
This is especially convenient when you consider that most dependency values are provided by classes.
@ -978,7 +947,6 @@ They can be object literals such as this one:
但是这些配置对象不总是类的实例,它们可能是对象,如下面这个:
<code-example path="dependency-injection/src/app/app.config.ts" region="config" title="src/app/app.config.ts (excerpt)" linenums="false">
</code-example>
What if you'd like to make this configuration object available for injection?
@ -1005,11 +973,9 @@ Unfortunately, you cannot use a TypeScript interface as a token:
`HERO_DI_CONFIG` 常量有一个接口:`AppConfig`。不幸的是,不能把 TypeScript 接口用作令牌:
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9-interface" linenums="false">
</code-example>
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-9-ctor-interface" linenums="false">
</code-example>
That seems strange if you're used to dependency injection in strongly typed languages, where
@ -1042,7 +1008,6 @@ The definition of such a token looks like this:
定义方式是这样的:
<code-example path="dependency-injection/src/app/app.config.ts" region="token" title="src/app/app.config.ts" linenums="false">
</code-example>
The type parameter, while optional, conveys the dependency's type to developers and tooling.
@ -1056,7 +1021,6 @@ Register the dependency provider using the `InjectionToken` object:
使用这个 `InjectionToken` 对象注册依赖的提供商:
<code-example path="dependency-injection/src/app/providers.component.ts" region="providers-9" linenums="false">
</code-example>
Now you can inject the configuration object into any constructor that needs it, with
@ -1065,7 +1029,6 @@ the help of an `@Inject` decorator:
现在,在 `@Inject` 装饰器的帮助下,这个配置对象可以注入到任何需要它的构造函数中:
<code-example path="dependency-injection/src/app/app.component.2.ts" region="ctor" title="src/app/app.component.ts" linenums="false">
</code-example>
<div class="l-sub-section">
@ -1098,11 +1061,9 @@ constructor argument with `@Optional()`:
可以把构造函数的参数标记为 `@Optional()`,告诉 Angular 该依赖是可选的:
<code-example path="dependency-injection/src/app/providers.component.ts" region="import-optional">
</code-example>
<code-example path="dependency-injection/src/app/providers.component.ts" region="provider-10-ctor" linenums="false">
</code-example>
When using `@Optional()`, your code must be prepared for a null value. If you
@ -1145,7 +1106,6 @@ here's an `InjectorComponent` that does.
但开发者很少直接使用它。
<code-example path="dependency-injection/src/app/injector.component.ts" region="injector" title="src/app/injector.component.ts">
</code-example>
An `Injector` is itself an injectable service.

View File

@ -23,9 +23,7 @@ For the simplest deployment, build for development and copy the output directory
使用开发环境进行构建
<code-example language="none" class="code-shell">
ng build
</code-example>
2. Copy _everything_ within the output folder (`dist/` by default) to a folder on the server.
@ -42,9 +40,7 @@ For the simplest deployment, build for development and copy the output directory
比如,如果 `index.html` 位于服务器上的 `/my/app/index.html` 路径下,就要把 *base href* 设置为 `<base href="/my/app/">`,就像这样:
<code-example language="none" class="code-shell">
ng build --base-href=/my/app/
</code-example>
You'll see that the `<base href>` is set properly in the generated `dist/index.html`.<br><br>
@ -84,9 +80,7 @@ starting with `--prod`.
### 使用 `--prod` 构建。
<code-example language="none" class="code-shell">
ng build --prod
</code-example>
The `--prod` _meta-flag_ engages the following optimization features.
@ -126,9 +120,7 @@ You may further reduce bundle sizes by adding the `build-optimizer` flag.
你还可以添加 `build-optimizer` 标志来进一步缩减打包体积。
<code-example language="none" class="code-shell">
ng build --prod --build-optimizer
</code-example>
See the [CLI Documentation](https://github.com/angular/angular-cli/wiki/build)
@ -148,9 +140,7 @@ console:
Angular 应用默认运行在开发模式下,正如在浏览器控制台中看到的如下信息:
<code-example format="nocode">
Angular is running in the development mode. Call enableProdMode() to enable the production mode.
</code-example>
Switching to _production mode_ can make it run faster by disabling development specific checks such as the dual change detection cycles.
@ -257,9 +247,7 @@ Install `source-map-explorer`:
安装 `source-map-explorer`
<code-example language="none" class="code-shell">
npm install source-map-explorer --save-dev
</code-example>
Build your app for production _including the source maps_
@ -267,9 +255,7 @@ Build your app for production _including the source maps_
构建*带源码映射*的生产版本
<code-example language="none" class="code-shell">
ng build --prod --sourcemaps
</code-example>
List the generated bundles in the `dist/` folder.
@ -277,9 +263,7 @@ List the generated bundles in the `dist/` folder.
列出 `dist/` 文件夹中生成的文件包。
<code-example language="none" class="code-shell">
ls dist/*.bundle.js
</code-example>
Run the explorer to generate a graphical representation of one of the bundles.
@ -289,9 +273,7 @@ The following example displays the graph for the _main_ bundle.
下面的例子中就是 `main` 这个文件包的图形。
<code-example language="none" class="code-shell">
node_modules/.bin/source-map-explorer dist/main.*.bundle.js
</code-example>
The `source-map-explorer` analyzes the source map generated with the bundle and draws a map of all dependencies,
@ -488,12 +470,10 @@ The list is by no means exhaustive, but should provide you with a good starting
[Webpack-Dev-Server](https://github.com/webpack/webpack-dev-server)在开发服务器的配置中设置了 `historyApiFallback`,代码如下:
<code-example>
historyApiFallback: {
disableDotRule: true,
htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
}
</code-example>
#### Production servers
@ -508,7 +488,6 @@ The list is by no means exhaustive, but should provide you with a good starting
代码如下([出处](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/)
<code-example format=".">
RewriteEngine On
&#35 If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
@ -517,7 +496,6 @@ The list is by no means exhaustive, but should provide you with a good starting
&#35 If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
</code-example>
* [NGinx](http://nginx.org/): use `try_files`, as described in
@ -527,9 +505,7 @@ modified to serve `index.html`:
[NGinx](http://nginx.org/):使用 `try_files` 指向 `index.html`,详细描述见[Web 应用的前端控制器模式](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#front-controller-pattern-web-apps)。
<code-example format=".">
try_files $uri $uri/ /index.html;
</code-example>
* [IIS](https://www.iis.net/): add a rewrite rule to `web.config`, similar to the one shown
@ -538,7 +514,6 @@ modified to serve `index.html`:
[IIS](https://www.iis.net/):往 `web.config` 中添加一条重写规则,类似于[这里](http://stackoverflow.com/a/26152011/2116927)
<code-example format='.'>
&lt;system.webServer&gt;
&lt;rewrite&gt;
&lt;rules&gt;
@ -577,7 +552,6 @@ and to
[Firebase 主机服务](https://firebase.google.com/docs/hosting/):添加一条[重写规则](https://firebase.google.com/docs/hosting/url-redirects-rewrites#section-rewrites)。
<code-example format=".">
"rewrites": [ {
"source": "**",
"destination": "/index.html"
@ -605,7 +579,6 @@ The server must be configured to accept the application's requests.
Read about how to enable CORS for specific servers at
<a href="http://enable-cors.org/server.html" title="Enabling CORS server">enable-cors.org</a>.
客户端应用对这种错误无能为力。
服务器必须配置成可以接受来自该应用的请求。
要了解如何对特定的服务器开启 CORS参见<a href="http://enable-cors.org/server.html" target="_blank" title="Enabling CORS server">enable-cors.org</a>

View File

@ -173,9 +173,7 @@ In either style, the template data bindings have the same access to the componen
默认情况下Angular CLI 生成组件时会带有模板文件,你可以通过参数覆盖它:
<code-example hideCopy language="sh" class="code-shell">
ng generate component hero -it
</code-example>
</div>
@ -295,9 +293,7 @@ of hero names into an array of `Hero` objects. For that you'll need a `Hero` cla
要将此绑定转换成使用对象,需要把这个英雄名字数组变成 `Hero` 对象数组。但首先得有一个 `Hero` 类。
<code-example language="sh" class="code-shell">
ng generate class hero
</code-example>
With the following code:

View File

@ -305,17 +305,13 @@ But there are times when an inline snippet is the better choice.
For terminal input and output, put the content between `<code-example>` tags, set the CSS class to `code-shell`, and set the language attribute to `sh` as in this example.
<code-example language="sh" class="code-shell">
npm start
</code-example>
```html
<code-example language="sh" class="code-shell">
npm start
</code-example>
```
@ -365,7 +361,6 @@ Here's the brief markup that produced that lengthy snippet:
<code-example
path="docs-style-guide/src/app/app.module.ts"
title="src/app/app.module.ts">
</code-example>
```
@ -398,7 +393,6 @@ The preferred way to un-ignore a file is to update the `content/examples/.gitign
!my-guide/src/something.js
!my-guide/more-javascript*.js
</code-example>
</div>
@ -430,7 +424,6 @@ Often you want to focus on a fragment of code within a sample code file. In this
<code-example
path="docs-style-guide/src/app/app.module.ts"
region="class">
</code-example>
First you surround that fragment in the source file with a named _docregion_ as described [below](#source-code-markup).
@ -441,7 +434,6 @@ Then you reference that _docregion_ in the `region` attribute of the `<code-exam
<code-example
path="docs-style-guide/src/app/app.module.ts"
region="class">
</code-example>
```
@ -472,13 +464,11 @@ Here's the markup for an "avoid" example in the
path="styleguide/src/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts"
region="example"
title="app/heroes/hero-button/hero-button.component.ts">
</code-example>
```
<code-example path="styleguide/src/05-03/app/heroes/shared/hero-button/hero-button.component.avoid.ts" region="example" title="app/heroes/hero-button/hero-button.component.ts">
</code-example>
{@a code-tabs}
@ -503,7 +493,6 @@ The next example displays multiple code tabs, each with its own title.
It demonstrates control over display of line numbers at both the `<code-tabs>` and `<code-pane>` levels.
<code-tabs linenums="false">
<code-pane
title="app.component.html"
path="docs-style-guide/src/app/app.component.html">
@ -522,7 +511,6 @@ It demonstrates control over display of line numbers at both the `<code-tabs>` a
title="package.json (scripts)"
path="docs-style-guide/package.1.json">
</code-pane>
</code-tabs>
Here's the markup for that example.
@ -533,7 +521,6 @@ The `linenums` attribute in the second pane restores line numbering for _itself
```html
<code-tabs linenums="false">
<code-pane
title="app.component.html"
path="docs-style-guide/src/app/app.component.html">
@ -552,7 +539,6 @@ The `linenums` attribute in the second pane restores line numbering for _itself
title="package.json (scripts)"
path="docs-style-guide/package.1.json">
</code-pane>
</code-tabs>
```
@ -685,7 +671,6 @@ Examine the `src/app/app.component.ts` file which defines two nested _#docregion
The inner, `class-skeleton` region appears twice, once to capture the code that opens the class definition and once to capture the code that closes the class definition.
<code-example linenums="false">
// #docplaster
...
// #docregion class, class-skeleton
@ -701,13 +686,11 @@ export class AppComponent {
// #docregion class-skeleton
}
// #enddocregion class, class-skeleton
</code-example>
Here's are the two corresponding code snippets displayed side-by-side.
<code-tabs>
<code-pane
title="app.component.ts (class)"
path="docs-style-guide/src/app/app.component.ts"
@ -718,7 +701,6 @@ Here's are the two corresponding code snippets displayed side-by-side.
path="docs-style-guide/src/app/app.component.ts"
region="class-skeleton">
</code-pane>
</code-tabs>
Some observations:
@ -953,7 +935,6 @@ For these reasons, it is often wise to add a custom anchor explicitly, just abov
text to which it applies, using the special `{@a name}` syntax like this.
<code-example language="html">
&#123;@a ugly-anchors&#125;
#### Ugly, long section header anchors
@ -1244,7 +1225,6 @@ Use HTML tables to present tabular data.
</style>
<table>
<tr>
<th>
@ -1266,7 +1246,6 @@ Use HTML tables to present tabular data.
</th>
</tr>
<tr>
<td>
@ -1290,7 +1269,6 @@ Use HTML tables to present tabular data.
</td>
</tr>
<tr>
<td>
@ -1316,7 +1294,6 @@ Use HTML tables to present tabular data.
</td>
</tr>
<tr>
<td>
@ -1340,7 +1317,6 @@ Use HTML tables to present tabular data.
</td>
</tr>
</table>
Here is the markup for this table.
@ -1352,7 +1328,6 @@ Here is the markup for this table.
</style>
<table>
<tr>
<th>
@ -1374,7 +1349,6 @@ Here is the markup for this table.
</th>
</tr>
<tr>
<td>
@ -1398,7 +1372,6 @@ Here is the markup for this table.
</td>
</tr>
<tr>
<td>
@ -1424,7 +1397,6 @@ Here is the markup for this table.
</td>
</tr>
<tr>
<td>
@ -1448,7 +1420,6 @@ Here is the markup for this table.
</td>
</tr>
</table>
```

View File

@ -266,5 +266,4 @@ The final form looks like this:
[Back to top](guide/dynamic-form#top)
[回到顶部](guide/dynamic-form#top)

View File

@ -12,7 +12,7 @@ A basic understanding of the following concepts:
* [Bootstrapping](guide/bootstrapping).
[引导](guide/bootstrapping)。
[引导启动](guide/bootstrapping)。
<hr />
@ -172,15 +172,15 @@ You may also be interested in the following:
* [Types of NgModules](guide/module-types)
[Angular 模块的分类](guide/module-types)
[NgModule 的分类](guide/module-types).
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
[使用 Angular 路由器实现惰性加载模块](guide/lazy-loading-ngmodules).
[使用 Angular 路由器惰性加载模块](guide/lazy-loading-ngmodules)
* [Providers](guide/providers).
[服务提供商](guide/providers).
[服务提供商](guide/providers)
* [NgModules FAQ](guide/ngmodule-faq).

View File

@ -16,7 +16,7 @@ A basic understanding of the following:
* [Bootstrapping](guide/bootstrapping).
[引导](guide/bootstrapping)。
[引导启动](guide/bootstrapping)。
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
@ -24,7 +24,7 @@ A basic understanding of the following:
* [Frequently Used Modules](guide/frequent-ngmodules).
[常用模块](guide/frequent-ngmodules).
[常用模块](guide/frequent-ngmodules)
For the final sample app with a feature module that this page describes,
see the <live-example></live-example>.
@ -118,7 +118,6 @@ This generates a folder for the new component within the customer-dashboard fold
这会在 `customer-dashboard` 中为新组件生成一个目录,并使用 `CustomerDashboardComponent` 的信息修改这个特性模块:
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="customer-dashboard-component" title="src/app/customer-dashboard/customer-dashboard.module.ts" linenums="false">
</code-example>
The `CustomerDashboardComponent` is now in the JavaScript import list at the top and added to the `declarations` array, which lets Angular know to associate this new component with this feature module.
@ -134,7 +133,6 @@ To incorporate the feature module into your app, you have to let the root module
要想把这个特性模块包含进应用中,你还得让根模块 `app.module.ts` 知道它。注意,在 `customer-dashboard.module.ts` 的底部导出了 `CustomerDashboardModule`。这样就把它暴露出来,以便其它模块可以拿到它。要想把它导入到 `AppModule` 中,就把它加入 `app.module.ts` 的导入表中,并将其加入 `imports` 数组:
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" title="src/app/app.module.ts" linenums="false">
</code-example>
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules dont expose their components.
@ -150,7 +148,6 @@ When the CLI generated the `CustomerDashboardComponent` for the feature module,
当 CLI 为这个特性模块生成 `CustomerDashboardComponent` 时,还包含一个模板 `customer-dashboard.component.html`,它带有如下页面脚本:
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" region="feature-template" title="src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" linenums="false">
</code-example>
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the `declarations` array, add an `exports` array containing `CustomerDashboardModule`:
@ -159,7 +156,6 @@ To see this HTML in the `AppComponent`, you first have to export the `CustomerDa
`customer-dashboard.module.ts` 中,`declarations` 数组的紧下方,加入一个包含 `CustomerDashboardModule``exports` 数组:
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="component-exports" title="src/app/customer-dashboard/customer-dashboard.module.ts" linenums="false">
</code-example>
Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-dashboard>`:
@ -167,7 +163,6 @@ Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-da
然后,在 `AppComponent``app.component.html` 中,加入标签 `<app-customer-dashboard>`
<code-example path="feature-modules/src/app/app.component.html" region="app-component-template" title="src/app/app.component.html" linenums="false">
</code-example>
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
@ -190,12 +185,12 @@ You may also be interested in the following:
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
[使用 Angular 路由器实现惰性加载模块](guide/lazy-loading-ngmodules).
[使用 Angular 路由器惰性加载模块](guide/lazy-loading-ngmodules)
* [Providers](guide/providers).
[服务提供商](guide/providers).
[服务提供商](guide/providers)
* [Types of Feature Modules](guide/module-types).
[Angular 模块的分类](guide/module-types)
[特性模块的分类](guide/module-types)。

View File

@ -140,7 +140,6 @@ built-in validators&mdash;this time, in function form. See below:
{@a reactive-component-class}
<code-example path="form-validation/src/app/reactive/hero-form-reactive.component.ts" region="form-group" title="reactive/hero-form-reactive.component.ts (validator functions)" linenums="false">
</code-example>
Note that:
@ -169,7 +168,6 @@ If you look at the template for the name input again, it is fairly similar to th
如果你到模板中找到 name 输入框,就会发现它和模板驱动的例子很相似。
<code-example path="form-validation/src/app/reactive/hero-form-reactive.component.html" region="name-with-error-msg" title="reactive/hero-form-reactive.component.html (name with error msg)" linenums="false">
</code-example>
Key takeaways:
@ -201,7 +199,6 @@ this guide. Here's what the definition of that function looks like:
考虑前面的[例子](guide/form-validation#reactive-component-class)中的 `forbiddenNameValidator` 函数。该函数的定义看起来是这样的:
<code-example path="form-validation/src/app/shared/forbidden-name.directive.ts" region="custom-validator" title="shared/forbidden-name.directive.ts (forbiddenNameValidator)" linenums="false">
</code-example>
The function is actually a factory that takes a regular expression to detect a _specific_ forbidden name and returns a validator function.
@ -241,7 +238,6 @@ to the `FormControl`.
在响应式表单组件中,添加自定义验证器相当简单。你所要做的一切就是直接把这个函数传给 `FormControl`
<code-example path="form-validation/src/app/reactive/hero-form-reactive.component.ts" region="custom-validator" title="reactive/hero-form-reactive.component.ts (validator functions)" linenums="false">
</code-example>
### Adding to template-driven forms
@ -263,7 +259,6 @@ with the `NG_VALIDATORS` provider, a provider with an extensible collection of v
Angular 在验证流程中的识别出指令的作用,是因为指令把自己注册到了 `NG_VALIDATORS` 提供商中,该提供商拥有一组可扩展的验证器。
<code-example path="form-validation/src/app/shared/forbidden-name.directive.ts" region="directive-providers" title="shared/forbidden-name.directive.ts (providers)" linenums="false">
</code-example>
The directive class then implements the `Validator` interface, so that it can easily integrate
@ -273,7 +268,6 @@ comes together:
然后该指令类实现了 `Validator` 接口,以便它能简单的与 Angular 表单集成在一起。这个指令的其余部分有助于你理解它们是如何协作的:
<code-example path="form-validation/src/app/shared/forbidden-name.directive.ts" region="directive" title="shared/forbidden-name.directive.ts (directive)">
</code-example>
Once the `ForbiddenValidatorDirective` is ready, you can simply add its selector, `appForbiddenName`, to any input element to activate it. For example:
@ -330,5 +324,4 @@ set the color of each form control's border.
**You can run the <live-example></live-example> to see the complete reactive and template-driven example code.**
**你可以运行<live-example></live-example>来查看完整的响应式和模板驱动表单的代码。**

View File

@ -49,7 +49,7 @@ This page shows you how to build a simple form from scratch. Along the way you'l
You can run the <live-example></live-example> in Stackblitz and download the code from there.
运行<live-example></live-example>来试用本页的代码。
你可以运行<live-example></live-example>,在 Stackblitz 中试用并下载本页的代码。
{@a template-driven}

View File

@ -8,7 +8,7 @@
A basic understanding of [Bootstrapping](guide/bootstrapping).
对[引导](guide/bootstrapping)有基本的解。
对[引导](guide/bootstrapping)有基本的解。
<hr>
@ -287,4 +287,4 @@ You may also be interested in the following:
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
[JavaScript 模块与 NgModules](guide/ngmodule-vs-jsmodule).
[JavaScript 模块与 NgModules](guide/ngmodule-vs-jsmodule)

View File

@ -83,7 +83,6 @@ For example, imagine three ES2015 modules in a `heroes` folder:
例如,设想在 `heroes` 目录下有三个 ES2015 模块:
<code-example>
// heroes/hero.component.ts
export class HeroComponent {}
@ -92,7 +91,6 @@ For example, imagine three ES2015 modules in a `heroes` folder:
// heroes/hero.service.ts
export class HeroService {}
</code-example>
Without a barrel, a consumer needs three import statements:
@ -100,11 +98,9 @@ Without a barrel, a consumer needs three import statements:
如果没有封装桶,消费者需要三条导入语句:
<code-example>
import { HeroComponent } from '../heroes/hero.component.ts';
import { Hero } from '../heroes/hero.model.ts';
import { HeroService } from '../heroes/hero.service.ts';
</code-example>
You can add a barrel to the `heroes` folder (called `index`, by convention) that exports all of these items:
@ -112,11 +108,9 @@ You can add a barrel to the `heroes` folder (called `index`, by convention) that
`heroes` 目录下添加一个封装桶(按约定叫做 `index`),它导出所有这三项:
<code-example>
export * from './hero.model.ts'; // re-export all of its exports
export * from './hero.service.ts'; // re-export all of its exports
export { HeroComponent } from './hero.component.ts'; // re-export the named thing
</code-example>
Now a consumer can import what it needs from the barrel.
@ -124,9 +118,7 @@ Now a consumer can import what it needs from the barrel.
现在,消费者就就可以从这个封装桶中导入它需要的东西了。
<code-example>
import { Hero, HeroService } from '../heroes'; // index is implied
</code-example>
The Angular [scoped packages](guide/glossary#scoped-package) each have a barrel named `index`.
@ -615,7 +607,6 @@ or displayed between element tags, as in this example.
在被赋值给元素属性或者显示在元素标签中之前,这些文本可能会先与周边的文本合并,参见下面的例子。
<code-example language="html" escape="html">
<label>My current hero is {{hero.name}}</label>
</code-example>
@ -870,7 +861,6 @@ Angular 管道是一个函数,用于把输入值转换成输出值以供[视
下面这个例子中,用内置的 `currency` 管道把数字值显示为本地货币格式。
<code-example language="html" escape="html">
<label>Price: </label>{{product.price | currency}}
</code-example>
@ -1251,5 +1241,4 @@ Angular 会在一个 Zone 区域中运行应用程序,在这个区域中,它
Learn more about zones in this
[Brian Ford video](https://www.youtube.com/watch?v=3IqtmUscE_U).
更多信息,见 [Brian Ford 的视频](https://www.youtube.com/watch?v=3IqtmUscE_U)。

View File

@ -45,7 +45,6 @@ Most apps do so in the root `AppModule`.
path="http/src/app/app.module.ts"
region="sketch"
title="app/app.module.ts (excerpt)" linenums="false">
</code-example>
Having imported `HttpClientModule` into the `AppModule`, you can inject the `HttpClient`
@ -57,7 +56,6 @@ into an application class as shown in the following `ConfigService` example.
path="http/src/app/config/config.service.ts"
region="proto"
title="app/config/config.service.ts (excerpt)" linenums="false">
</code-example>
## Getting JSON data
@ -74,7 +72,6 @@ that specifies resource URLs.
<code-example
path="http/src/assets/config.json"
title="assets/config.json" linenums="false">
</code-example>
The `ConfigService` fetches this file with a `get()` method on `HttpClient`.
@ -85,7 +82,6 @@ The `ConfigService` fetches this file with a `get()` method on `HttpClient`.
path="http/src/app/config/config.service.ts"
region="getConfig_1"
title="app/config/config.service.ts (getConfig v.1)" linenums="false">
</code-example>
A component, such as `ConfigComponent`, injects the `ConfigService` and calls
@ -97,7 +93,6 @@ the `getConfig` service method.
path="http/src/app/config/config.component.ts"
region="v1"
title="app/config/config.component.ts (showConfig v.1)" linenums="false">
</code-example>
Because the service method returns an `Observable` of configuration data,
@ -148,7 +143,6 @@ The subscribe callback above requires bracket notation to extract the data value
<code-example
path="http/src/app/config/config.component.ts"
region="v1_callback" linenums="false">
</code-example>
You can't write `data.heroesUrl` because TypeScript correctly complains that the `data` object from the service does not have a `heroesUrl` property.
@ -170,7 +164,6 @@ First, define an interface with the correct shape:
<code-example
path="http/src/app/config/config.service.ts"
region="config-interface" linenums="false">
</code-example>
Then, specify that interface as the `HttpClient.get()` call's type parameter in the service:
@ -181,7 +174,6 @@ Then, specify that interface as the `HttpClient.get()` call's type parameter in
path="http/src/app/config/config.service.ts"
region="getConfig_2"
title="app/config/config.service.ts (getConfig v.2)" linenums="false">
</code-example>
The callback in the updated component method receives a typed data object, which is
@ -193,7 +185,6 @@ easier and safer to consume:
path="http/src/app/config/config.component.ts"
region="v2"
title="app/config/config.component.ts (showConfig v.2)" linenums="false">
</code-example>
### Reading the full response
@ -211,7 +202,6 @@ Tell `HttpClient` that you want the full response with the `observe` option:
<code-example
path="http/src/app/config/config.service.ts"
region="getConfigResponse" linenums="false">
</code-example>
Now `HttpClient.get()` returns an `Observable` of typed `HttpResponse` rather than just the JSON data.
@ -227,7 +217,6 @@ The component's `showConfigResponse()` method displays the response headers as w
region="showConfigResponse"
title="app/config/config.component.ts (showConfigResponse)"
linenums="false">
</code-example>
As you can see, the response object has a `body` property of the correct type.
@ -251,7 +240,6 @@ You _could_ handle in the component by adding a second callback to the `.subscri
region="v3"
title="app/config/config.component.ts (showConfig v.3 with error handling)"
linenums="false">
</code-example>
It's certainly a good idea to give the user some kind of feedback when data access fails.
@ -296,7 +284,6 @@ You might first devise an error handler like this one:
path="http/src/app/config/config.service.ts"
region="handleError"
title="app/config/config.service.ts (handleError)" linenums="false">
</code-example>
Notice that this handler returns an RxJS [`ErrorObservable`](#rxjs) with a user-friendly error message.
@ -315,7 +302,6 @@ and _pipe them through_ to the error handler.
path="http/src/app/config/config.service.ts"
region="getConfig_3"
title="app/config/config.service.ts (getConfig v.3 with error handler)" linenums="false">
</code-example>
### `retry()`
@ -341,7 +327,6 @@ _Pipe_ it onto the `HttpClient` method result just before the error handler.
path="http/src/app/config/config.service.ts"
region="getConfig"
title="app/config/config.service.ts (getConfig with retry)" linenums="false">
</code-example>
{@a rxjs}
@ -377,7 +362,6 @@ If you're following along with these code snippets, note that you must import th
path="http/src/app/config/config.service.ts"
region="rxjs-imports"
title="app/config/config.service.ts (RxJS imports)" linenums="false">
</code-example>
## Requesting non-JSON data
@ -396,7 +380,6 @@ as an `Observable<string>`.
path="http/src/app/downloader/downloader.service.ts"
region="getTextFile"
title="app/downloader/downloader.service.ts (getTextFile)" linenums="false">
</code-example>
`HttpClient.get()` returns a string rather than the default JSON because of the `responseType` option.
@ -415,7 +398,6 @@ A `download()` method in the `DownloaderComponent` initiates the request by subs
path="http/src/app/downloader/downloader.component.ts"
region="download"
title="app/downloader/downloader.component.ts (download)" linenums="false">
</code-example>
## Sending data to the server
@ -457,7 +439,6 @@ to every `HttpClient` save method.
path="http/src/app/heroes/heroes.service.ts"
region="http-options"
title="app/heroes/heroes.service.ts (httpOptions)" linenums="false">
</code-example>
### Making a POST request
@ -474,7 +455,6 @@ In the following example, the `HeroService` posts when adding a hero to the data
path="http/src/app/heroes/heroes.service.ts"
region="addHero"
title="app/heroes/heroes.service.ts (addHero)" linenums="false">
</code-example>
The `HttpClient.post()` method is similar to `get()` in that it has a type parameter
@ -510,7 +490,6 @@ the `Observable` returned by this service method.
path="http/src/app/heroes/heroes.component.ts"
region="add-hero-subscribe"
title="app/heroes/heroes.component.ts (addHero)" linenums="false">
</code-example>
When the server responds successfully with the newly added hero, the component adds
@ -531,7 +510,6 @@ in the request URL.
path="http/src/app/heroes/heroes.service.ts"
region="deleteHero"
title="app/heroes/heroes.service.ts (deleteHero)" linenums="false">
</code-example>
The `HeroesComponent` initiates the actual DELETE operation by subscribing to
@ -543,7 +521,6 @@ the `Observable` returned by this service method.
path="http/src/app/heroes/heroes.component.ts"
region="delete-hero-subscribe"
title="app/heroes/heroes.component.ts (deleteHero)" linenums="false">
</code-example>
<div class="alert is-important">
@ -570,7 +547,6 @@ Merely calling `HeroService.deleteHero()` **does not initiate the DELETE request
<code-example
path="http/src/app/heroes/heroes.component.ts"
region="delete-hero-no-subscribe" linenums="false">
</code-example>
{@a always-subscribe}
@ -643,7 +619,6 @@ The following `HeroService` example is just like the POST example.
path="http/src/app/heroes/heroes.service.ts"
region="updateHero"
title="app/heroes/heroes.service.ts (updateHero)" linenums="false">
</code-example>
For the reasons [explained above](#always-subscribe), the caller (`HeroesComponent.update()` in this case) must `subscribe()` to the observable returned from the `HttpClient.put()`
@ -698,7 +673,6 @@ before making the next request.
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="update-headers" linenums="false">
</code-example>
#### URL Parameters
@ -714,14 +688,13 @@ Here is a `searchHeroes` method that queries for heroes whose names contain the
<code-example
path="http/src/app/heroes/heroes.service.ts"
region="searchHeroes" linenums="false">
</code-example>
If there is a search term, the code constructs an options object with an HTML URL encoded search parameter. If the term were "foo", the GET request URL would be `api/heroes/?name=foo`.
如果有搜索词,这段代码就会构造一个包含进行过 URL 编码的搜索词的选项对象。如果这个搜索词是“foo”这个 GET 请求的 URL 就会是 `api/heroes/?name=foo`
The `HttpParams` are immutable so you'll have to use the `set()` method to update the options.
The `HttpParms` are immutable so you'll have to use the `set()` method to update the options.
`HttpParams` 是不可变的,所以你也要使用 `set()` 方法来修改这些选项。
@ -746,7 +719,6 @@ Here's a pertinent excerpt from the template:
path="http/src/app/package-search/package-search.component.html"
region="search"
title="app/package-search/package-search.component.html (search)">
</code-example>
The `(keyup)` event binding sends every keystroke to the component's `search()` method.
@ -765,7 +737,6 @@ That's easy to implement with RxJS operators, as shown in this excerpt.
path="http/src/app/package-search/package-search.component.ts"
region="debounce"
title="app/package-search/package-search.component.ts (excerpt))">
</code-example>
The `searchText$` is the sequence of search-box values coming from the user.
@ -875,15 +846,14 @@ To implement an interceptor, declare a class that implements the `intercept()` m
要实现拦截器,就要实现一个实现了 `HttpInterceptor` 接口中的 `intercept()` 方法的类。
Here is a do-nothing _noop_ interceptor that simply passes the request through without touching it:
Here is a do-nothing _noop_ interceptor that simply passes the request through without touching it:
这里是一个什么也不做的*空白*拦截器,它只会不做任何修改的传递这个请求。
这里是一个什么也不做的*空白*拦截器,它只会不做任何修改的传递这个请求。
<code-example
path="http/src/app/http-interceptors/noop-interceptor.ts"
title="app/http-interceptors/noop-interceptor.ts"
linenums="false">
</code-example>
The `intercept` method transforms a request into an `Observable` that eventually returns the HTTP response.
@ -963,7 +933,6 @@ write the `NoopInterceptor` provider like this:
<code-example
path="http/src/app/http-interceptors/index.ts"
region="noop-provider" linenums="false">
</code-example>
Note the `multi: true` option.
@ -990,7 +959,6 @@ Consider creating a "barrel" file that gathers all the interceptor providers int
path="http/src/app/http-interceptors/index.ts"
region="interceptor-providers"
title="app/http-interceptors/index.ts" linenums="false">
</code-example>
Then import and add it to the `AppModule` _providers array_ like this:
@ -1001,7 +969,6 @@ Then import and add it to the `AppModule` _providers array_ like this:
path="http/src/app/app.module.ts"
region="interceptor-providers"
title="app/app.module.ts (interceptor providers)" linenums="false">
</code-example>
As you create new interceptors, add them to the `httpInterceptorProviders` array and
@ -1100,7 +1067,6 @@ You can clone and modify the request in a single step as in this example.
path="http/src/app/http-interceptors/ensure-https-interceptor.ts"
region="excerpt"
title="app/http-interceptors/ensure-https-interceptor.ts (excerpt)" linenums="false">
</code-example>
The `clone()` method's hash argument allows you to mutate specific properties of the request while copying the others.
@ -1131,7 +1097,6 @@ If you must mutate the request body, copy it first, change the copy,
path="http/src/app/http-interceptors/trim-name-interceptor.ts"
region="excerpt"
title="app/http-interceptors/trim-name-interceptor.ts (excerpt)" linenums="false">
</code-example>
##### Clearing the request body
@ -1174,7 +1139,6 @@ adds an authorization header with that token to every outgoing request:
<code-example
path="http/src/app/http-interceptors/auth-interceptor.ts"
title="app/http-interceptors/auth-interceptor.ts">
</code-example>
The practice of cloning a request to set new headers is so common that
@ -1185,7 +1149,6 @@ there's a `setHeaders` shortcut for it:
<code-example
path="http/src/app/http-interceptors/auth-interceptor.ts"
region="set-header-shortcut">
</code-example>
An interceptor that alters headers can be used for a number of different operations, including:
@ -1223,7 +1186,6 @@ with the injected `MessageService`.
path="http/src/app/http-interceptors/logging-interceptor.ts"
region="excerpt"
title="app/http-interceptors/logging-interceptor.ts)">
</code-example>
The RxJS `tap` operator captures whether the request succeed or failed.
@ -1259,7 +1221,6 @@ The `CachingInterceptor` demonstrates this approach.
path="http/src/app/http-interceptors/caching-interceptor.ts"
region="v1"
title="app/http-interceptors/caching-interceptor.ts)" linenums="false">
</code-example>
The `isCachable()` function determines if the request is cachable.
@ -1287,7 +1248,6 @@ If a cachable request is not in cache, the code calls `sendRequest`.
<code-example
path="http/src/app/http-interceptors/caching-interceptor.ts"
region="send-request">
</code-example>
The `sendRequest` function creates a [request clone](#immutability) without headers
@ -1343,7 +1303,6 @@ and emits again later with the updated search results.
<code-example
path="http/src/app/http-interceptors/caching-interceptor.ts"
region="intercept-refresh">
</code-example>
The _cache-then-refresh_ option is triggered by the presence of a **custom `x-refresh` header**.
@ -1407,7 +1366,6 @@ with the `reportProgress` option set true to enable tracking of progress events.
path="http/src/app/uploader/uploader.service.ts"
region="upload-request"
title="app/uploader/uploader.service.ts (upload request)">
</code-example>
<div class="alert is-important">
@ -1427,7 +1385,6 @@ returns an `Observable` of `HttpEvents`, the same events processed by intercepto
path="http/src/app/uploader/uploader.service.ts"
region="upload-body"
title="app/uploader/uploader.service.ts (upload body)" linenums="false">
</code-example>
The `getEventMessage` method interprets each type of `HttpEvent` in the event stream.
@ -1438,7 +1395,6 @@ The `getEventMessage` method interprets each type of `HttpEvent` in the event st
path="http/src/app/uploader/uploader.service.ts"
region="getEventMessage"
title="app/uploader/uploader.service.ts (getEventMessage)" linenums="false">
</code-example>
<div class="alert is-helpful">
@ -1501,7 +1457,6 @@ use `HttpClientXsrfModule.withOptions()` to override the defaults.
path="http/src/app/app.module.ts"
region="xsrf"
linenums="false">
</code-example>
## Testing HTTP requests
@ -1565,7 +1520,6 @@ along with the other symbols your tests require.
path="http/src/testing/http-client.spec.ts"
region="imports"
title="app/testing/http-client.spec.ts (imports)" linenums="false">
</code-example>
Then add the `HttpClientTestingModule` to the `TestBed` and continue with
@ -1577,7 +1531,6 @@ the setup of the _service-under-test_.
path="http/src/testing/http-client.spec.ts"
region="setup"
title="app/testing/http-client.spec.ts(setup)" linenums="false">
</code-example>
Now requests made in the course of your tests will hit the testing backend instead of the normal backend.
@ -1601,7 +1554,6 @@ Now you can write a test that expects a GET Request to occur and provides a mock
path="http/src/testing/http-client.spec.ts"
region="get-test"
title="app/testing/http-client.spec.ts(httpClient.get)" linenums="false">
</code-example>
The last step, verifying that no requests remain outstanding, is common enough for you to move it into an `afterEach()` step:
@ -1612,7 +1564,6 @@ The last step, verifying that no requests remain outstanding, is common enough f
path="http/src/testing/http-client.spec.ts"
region="afterEach"
linenums="false">
</code-example>
#### Custom request expectations
@ -1629,7 +1580,6 @@ For example, you could look for an outgoing request that has an authorization he
path="http/src/testing/http-client.spec.ts"
region="predicate"
linenums="false">
</code-example>
As with the previous `expectOne()`,
@ -1652,7 +1602,6 @@ you are responsible for flushing and verifying them.
path="http/src/testing/http-client.spec.ts"
region="multi-request"
linenums="false">
</code-example>
### Testing for errors
@ -1671,5 +1620,4 @@ Call `request.error()` with an `ErrorEvent` instead of `request.flush()`, as in
path="http/src/testing/http-client.spec.ts"
region="404"
linenums="false">
</code-example>

View File

@ -85,9 +85,7 @@ of the locale id that you want to use:
要把你的应用的地区改为其它值,可以使用 CLI 参数 `--locale` 来传入你要使用的地区标识:
<code-example language="sh" class="code-shell">
ng serve --aot --locale fr
</code-example>
If you use JIT, you also need to define the `LOCALE_ID` provider in your main module:
@ -95,7 +93,6 @@ If you use JIT, you also need to define the `LOCALE_ID` provider in your main mo
如果要使用 JIT你就得在你的主模块中定义 `LOCALE_ID` 这个服务提供商:
<code-example path="i18n/doc-files/app.module.ts" title="src/app/app.module.ts" linenums="false">
</code-example>
For more information about Unicode locale identifiers, see the
@ -150,7 +147,6 @@ If you want to import locale data for other languages, you can do it manually:
如果还要为其它语言导入本地化数据,你可以手工完成它:
<code-example path="i18n/doc-files/app.locale_data.ts" region="import-locale" title="src/app/app.module.ts" linenums="false">
</code-example>
The first parameter is an object containing the locale data imported from `@angular/common/locales`.
@ -174,7 +170,6 @@ import from `@angular/common/locales/extra`. An error message informs you when t
不过有些高级的格式选项只存在于从 `@angular/common/locales/extra` 中导入的扩展数据集中。遇到这种情况,你就会收到一条错误信息。
<code-example path="i18n/doc-files/app.locale_data_extra.ts" region="import-locale-extra" title="src/app/app.module.ts" linenums="false">
</code-example>
<div class="l-sub-section">
@ -243,7 +238,6 @@ In the example below, an `<h1>` tag displays a simple English language greeting,
在下面的例子中,`<h1>`标签显示了一句简单的英文问候语“Hello i18n!”
<code-example path="i18n/doc-files/app.component.html" region="greeting" title="src/app/app.component.html" linenums="false">
</code-example>
To mark the greeting for translation, add the `i18n` attribute to the `<h1>` tag.
@ -251,7 +245,6 @@ To mark the greeting for translation, add the `i18n` attribute to the `<h1>` tag
要想把它标记为需要翻译的文本,就给 `<h1>` 标签添加上 `i18n` 属性。
<code-example path="i18n/doc-files/app.component.html" region="i18n-attribute" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="alert is-helpful">
@ -280,7 +273,6 @@ example below:
你可以用 `i18n` 属性的值来添加这些文本信息的描述,例子如下:
<code-example path="i18n/doc-files/app.component.html" region="i18n-attribute-desc" title="src/app/app.component.html" linenums="false">
</code-example>
The translator may also need to know the meaning or intent of the text message within this particular
@ -294,7 +286,6 @@ separating it from the _description_ with the `|` character: `<meaning>|<descrip
在描述的前面,你可以用 `i18n` 开头的属性值来为指定的字符串添加一些上下文含义,用 `|` 将其与描述文字隔开(`<意图>|<描述>`)。
<code-example path="i18n/doc-files/app.component.html" region="i18n-attribute-meaning" title="src/app/app.component.html" linenums="false">
</code-example>
All occurrences of a text message that have the same meaning will have the same translation.
@ -323,7 +314,6 @@ attribute in a template. By default, it assigns each translation unit a unique i
Angular 的 `i18n` 提取工具会为模板中每个带有 `i18n` 属性的元素生成一个*翻译单元translation unit*条目,并保存到一个文件中。默认情况下,它为每个翻译单元指定一个唯一的 `id`,就像这样:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="generated-id" linenums="false">
</code-example>
When you change the translatable text, the extractor tool generates a new id for that translation unit.
@ -339,7 +329,6 @@ The example below defines the custom id `introductionHeader`:
下面这个例子就定义了一个自定义 id `introductionHeader`
<code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-solo-id' title='app/app.component.html' linenums="false">
</code-example>
When you specify a custom id, the extractor tool and compiler generate a translation unit with that
@ -348,7 +337,6 @@ custom id.
一旦你指定了自定义 id提取工具和编译器就会用*你的自定义 id` 生成一个翻译单元,而不会再改变它。
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="custom-id" linenums="false">
</code-example>
The custom id is persistent. The extractor tool does not change it when the translatable text changes.
@ -369,7 +357,6 @@ by the custom `id`:
下面的例子中,`i18n` 的属性中中就包含了一条跟在自定义 `id` 后面的描述信息:
<code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-id' title='app/app.component.html' linenums="false">
</code-example>
You also can add a meaning, as shown in this example:
@ -377,7 +364,6 @@ You also can add a meaning, as shown in this example:
你还可以添加含义,例子如下:
<code-example path='i18n/doc-files/app.component.html' region='i18n-attribute-meaning-and-id' title='app/app.component.html' linenums="false">
</code-example>
#### Define unique custom ids
@ -446,7 +432,6 @@ The `<ng-container>` is transformed into an html comment:
但如果由于某些原因(比如 CSS 结构方面的考虑),你可能不希望仅仅为了翻译而创建一个新的 DOM 元素,那么也可以把这段文本包裹进一个 `<ng-container>` 元素中。`<ng-container>` 将被转换成一个 HTML 注释:
<code-example path="i18n/src/app/app.component.html" region="i18n-ng-container" title="src/app/app.component.html" linenums="false">
</code-example>
{@a translate-attributes}
@ -462,7 +447,6 @@ For example, assume that your template has an image with a `title` attribute:
比如,假设你的模板中有一个带 `title` 属性的图片:
<code-example path="i18n/doc-files/app.component.html" region="i18n-title" title="src/app/app.component.html" linenums="false">
</code-example>
This `title` attribute needs to be translated.
@ -477,7 +461,6 @@ where `x` is the name of the attribute to translate. The following example shows
下面的例子中演示了如何通过给 `img` 标签添加 `i18n-title` 属性来把 `title` 属性标记为待翻译的。
<code-example path="i18n/src/app/app.component.html" region="i18n-title-translate" title="src/app/app.component.html" linenums="false">
</code-example>
This technique works for any attribute of any element.
@ -514,7 +497,6 @@ based on when the update occurred:
下面这个例子示范了如何使用 ICU 表达式 `plural` 来根据这次修改发生的时间显示这三个选项之一:
<code-example path="i18n/src/app/app.component.html" region="i18n-plural" title="src/app/app.component.html" linenums="false">
</code-example>
* The first parameter is the key. It is bound to the component property (`minutes`), which determines
@ -620,7 +602,6 @@ The message maps those values to the appropriate translations:
这个消息会把那些值映射到适当的翻译文本:
<code-example path="i18n/src/app/app.component.html" region="i18n-select" title="src/app/app.component.html" linenums="false">
</code-example>
{@a nesting-ICUS}
@ -634,7 +615,6 @@ You can also nest different ICU expressions together, as shown in this example:
你也可以把不同的 ICU 表达式嵌套在一起,比如:
<code-example path="i18n/src/app/app.component.html" region="i18n-nested" title="src/app/app.component.html">
</code-example>
{@a ng-xi18n}
@ -653,9 +633,7 @@ Open a terminal window at the root of the app project and enter the `ng xi18n` c
在应用的项目根目录打开一个终端窗口,并输入 `ng xi18n` 命令:
<code-example language="sh" class="code-shell">
ng xi18n
</code-example>
By default, the tool generates a translation file named `messages.xlf` in the
@ -711,11 +689,9 @@ these example commands:
你可以使用 `--i18nFormat` 来明确指定想用的格式,范例如下:
<code-example language="sh" class="code-shell">
ng xi18n --i18nFormat=xlf
ng xi18n --i18nFormat=xlf2
ng xi18n --i18nFormat=xmb
</code-example>
The sample in this guide uses the default XLIFF 1.2 format.
@ -870,7 +846,8 @@ This sample file is easy to translate without a special editor or knowledge of F
打开 `messages.fr.xlf` 并找到第一个 `<trans-unit>` 区:
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello-before" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false"></code-example>
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello-before" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
> This XML element represents the translation of the `<h1>` greeting tag that you marked with the
`i18n` attribute earlier in this guide.
@ -891,13 +868,15 @@ This sample file is easy to translate without a special editor or knowledge of F
复制 `<source/>` 标记,把它改名为 `target`,并把它的内容改为法语版的 “greeting”。
如果你要做的是更复杂的翻译,可能会使用由源文本、描述信息和含义等提供的信息和上下文来给出更恰当的法语翻译。
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;, after translation)" linenums="false"></code-example>
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-hello" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;, after translation)" linenums="false">
</code-example>
3. Translate the other text nodes the same way:
用同样的方式翻译其它文本节点:
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-other-nodes" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false"></code-example>
> <code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-other-nodes" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
<div class="alert is-important">
@ -942,7 +921,6 @@ To translate a `plural`, translate its ICU format match values:
要翻译一个复数,就要翻译它的 ICU 格式中匹配的值:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-plural" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
You can add or remove plural cases, with each language having its own cardinality. (See
@ -961,7 +939,6 @@ Below is the content of our example `select` ICU expression in the component tem
下面是组件模板中的 ICU 表达式 `select` 的例子:
<code-example path="i18n/src/app/app.component.html" region="i18n-select" title="src/app/app.component.html" linenums="false">
</code-example>
The extraction tool broke that into two translation units because ICU expressions are extracted
@ -980,7 +957,6 @@ the placeholder, the ICU expression will not be present in your translated app.
如果删除了占位符ICU 表达式就不会出现在翻译后的应用中。
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-1" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
The second translation unit, immediately below the first one, contains the `select` message.
@ -989,7 +965,6 @@ Translate that as well.
第一个翻译单元的紧下方就是第二个翻译单元,包含 `select` 中的消息。照样翻译它。
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-select-2" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
Here they are together, after translation:
@ -997,7 +972,6 @@ Here they are together, after translation:
在翻译之后,它们会放在一起:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translated-select" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
{@a translate-nested}
@ -1013,7 +987,6 @@ two translation units. The first one contains the text outside of the nested exp
第一个包含嵌套表达式之外的文本:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested-1" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
The second unit contains the complete nested expression:
@ -1021,7 +994,6 @@ The second unit contains the complete nested expression:
第二个包含完整的嵌套表达式:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested-2" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
And both together:
@ -1029,7 +1001,6 @@ And both together:
放在一起时:
<code-example path="i18n/doc-files/messages.fr.xlf.html" region="translate-nested" title="src/locale/messages.fr.xlf (&lt;trans-unit&gt;)" linenums="false">
</code-example>
The entire template translation is complete. The next section describes how to load that translation
@ -1048,7 +1019,6 @@ The sample app and its translation file are now as follows:
下面是例子应用及其翻译文件:
<code-tabs>
<code-pane title="src/app/app.component.html" path="i18n/src/app/app.component.html">
</code-pane>
<code-pane title="src/app/app.component.ts" path="i18n/src/app/app.component.ts">
@ -1059,7 +1029,6 @@ The sample app and its translation file are now as follows:
</code-pane>
<code-pane title="src/locale/messages.fr.xlf" path="i18n/doc-files/messages.fr.xlf.html">
</code-pane>
</code-tabs>
{@a merge}
@ -1144,9 +1113,7 @@ guide:
下面的例子演示了如何使用前面部分创建的法语文件来启动开发服务器:
<code-example language="sh" class="code-shell">
ng serve --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr
</code-example>
{@a merge-jit}
@ -1196,7 +1163,6 @@ behavior of the compiler. You can use it to provide the translation providers:
在下面的 `src/app/i18n-providers.ts` 文件的 `getTranslationProviders()` 函数中,根据用户的**语言环境**和对应的翻译文件构建这些提供商:
<code-example path="i18n/doc-files/main.2.ts" title="src/main.ts">
</code-example>
Then provide the `LOCALE_ID` in the main module:
@ -1204,7 +1170,6 @@ Then provide the `LOCALE_ID` in the main module:
然后在主文件包中提供 `LOCALE_ID`
<code-example path="i18n/doc-files/app.module.ts" title="src/app/app.module.ts" linenums="false">
</code-example>
{@a missing-translation}
@ -1238,9 +1203,7 @@ If you use the AOT compiler, specify the warning level by using the CLI paramete
如果你使用 AOT 编译器,可以使用 CLI 参数 `--missingTranslation` 来指定警告级别。下面的例子示范了如何把警告级别设置为 `error`
<code-example language="sh" class="code-shell">
ng serve --aot --missingTranslation=error
</code-example>
If you use the JIT compiler, specify the warning level in the compiler config at bootstrap by adding
@ -1250,5 +1213,4 @@ error:
如果你要使用 JIT 编译器,就在启动时往编译器的配置中添加一个 `MissingTranslationStrategy` 属性来指定警告级别。下面的例子示范了如何把警告级别设置为 `error`
<code-example path="i18n/doc-files/main.3.ts" title="src/main.ts">
</code-example>

View File

@ -257,5 +257,4 @@ For more in-depth information, see the
For more information, see [Chuck Jazdzewski's presentation](https://www.youtube.com/watch?v=ez3R0Gi4z5A&t=368s) on the Angular Language
Service from [ng-conf](https://www.ng-conf.org/) 2017.
要了解更多信息,参见 [ng-conf](https://www.ng-conf.org/) 2017 中 [Chuck Jazdzewski 的演讲](https://www.youtube.com/watch?v=ez3R0Gi4z5A&t=368s) 中讲解的 Angular 语言服务。

View File

@ -355,7 +355,7 @@ CLI 还会把 `RouterModule.forChild(routes)` 添加到各个特性模块中。
You may also be interested in the following:
你可能还对下列内容感兴趣:
你可能还对下列内容感兴趣:
* [Routing and Navigation](guide/router).
@ -363,7 +363,7 @@ You may also be interested in the following:
* [Providers](guide/providers).
[提供商](guide/providers)。
[服务提供商](guide/providers)。
* [Types of Feature Modules](guide/module-types).

View File

@ -62,7 +62,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
<table width="100%">
<col width="20%"></col>
<col width="80%"></col>
<tr>
<th>
@ -82,7 +81,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</th>
</tr>
<tr style='vertical-align:top'>
<td>
@ -106,7 +104,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -129,7 +126,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -151,7 +147,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -173,7 +168,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -195,7 +189,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -217,7 +210,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -239,7 +231,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -263,7 +254,6 @@ calls the lifecycle hook methods in the following sequence at specific moments:
</td>
</tr>
</table>
{@a interface-optional}
@ -335,7 +325,6 @@ Here's a brief description of each exercise:
<table width="100%">
<col width="20%"></col>
<col width="80%"></col>
<tr>
<th>
@ -355,7 +344,6 @@ Here's a brief description of each exercise:
</th>
</tr>
<tr style='vertical-align:top'>
<td>
@ -374,7 +362,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -399,7 +386,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -420,7 +406,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -440,7 +425,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -460,7 +444,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -481,7 +464,6 @@ Here's a brief description of each exercise:
</td>
</tr>
<tr style='vertical-align:top'>
<td>
@ -510,7 +492,6 @@ Here's a brief description of each exercise:
</td>
</tr>
</table>
The remainder of this page discusses selected exercises in further detail.

View File

@ -115,7 +115,6 @@ typical characteristics, in real world apps, you may see hybrids.
</td>
</tr>
<tr>
<td>
@ -299,7 +298,6 @@ The following table summarizes the key characteristics of each feature module gr
下表中汇总了各种特性模块类型的关键特征。
<table>
<tr>
<th style="vertical-align: top">
@ -559,7 +557,6 @@ The following table summarizes the key characteristics of each feature module gr
</td>
</tr>
</table>
<hr />
@ -570,7 +567,7 @@ The following table summarizes the key characteristics of each feature module gr
You may also be interested in the following:
你可能还对下列内容感兴趣:
你可能还对下列内容感兴趣:
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).

View File

@ -139,7 +139,9 @@ The following table summarizes the `@NgModule` metadata properties.
</li>
</ul>
</li>
</ol>
Components, directives, and pipes must belong to _exactly_ one module.
@ -402,7 +404,7 @@ You may also be interested in the following:
* [Providers](guide/providers).
[提供商](guide/providers)。
[服务提供商](guide/providers)。
* [Types of Feature Modules](guide/module-types).

View File

@ -803,7 +803,6 @@ Here is a custom constructor for an NgModule called `CoreModule`.
某些 Angular 模块(例如 `BrowserModule`)就实现了一个像 Angular 模块那一章的 `CoreModule` 构造函数那样的守卫。
<code-example path="ngmodule-faq/src/app/core/core.module.ts" region="ctor" title="src/app/core/core.module.ts (Constructor)" linenums="false">
</code-example>
<hr/>
@ -1133,5 +1132,4 @@ the Angular compiler incorporates them into compiled component code too.
`@NgModule` metadata tells the Angular compiler what components to compile for this module and
how to link this module with other modules.
`@NgModule` 元数据告诉*Angular 编译器*要为当前模块编译哪些组件,以及如何把当前模块和其它模块链接起来。

View File

@ -126,4 +126,4 @@ For more information on NgModules, see:
* [Providers](guide/providers).
[服务提供商](guide/providers).
[服务提供商](guide/providers)

View File

@ -121,7 +121,6 @@ The CLI generates the following basic app module when creating a new app.
CLI 在创建新应用时会生成下列基本的应用模块。
<code-example path="bootstrapping/src/app/app.module.ts" region="whole-ngmodule" title="src/app/app.module.ts" linenums="false">
</code-example>
At the top are the import statements. The next section is where you configure the `@NgModule` by stating what components and directives belong to it (`declarations`) as well as which other modules it uses (`imports`). This page builds on [Bootstrapping](guide/bootstrapping), which covers the structure of an NgModule in detail. If you need more information on the structure of an `@NgModule`, be sure to read [Bootstrapping](guide/bootstrapping).
@ -137,7 +136,7 @@ At the top are the import statements. The next section is where you configure th
You may also be interested in the following:
你可能还对下列内容感兴趣:
你可能还对下列内容感兴趣:
* [Feature Modules](guide/feature-modules).
@ -149,7 +148,7 @@ You may also be interested in the following:
* [Providers](guide/providers).
[提供商](guide/providers)。
[服务提供商](guide/providers)。
* [Types of NgModules](guide/module-types).

View File

@ -280,5 +280,4 @@ The browser downloads this bundle, not the original package files.
See the [Deployment](guide/deployment) to learn more.
参见[部署](guide/deployment)一章了解详情。

View File

@ -52,11 +52,11 @@ A handler for receiving observable notifications implements the `Observer` inter
用于接收可观察对象通知的处理器要实现 `Observer` 接口。这个对象定义了一些回调函数来处理可观察对象可能会发来的三种通知:
| <p>Notification type</p><p>通知类型</p> | <p>Description</p><p>说明</p> |
| <t>Notification type</t><t>通知类型</t> | <t>Description</t><t>说明</t> |
|:---------|:-------------------------------------------|
| `next` | <p>Required. A handler for each delivered value. Called zero or more times after execution starts.</p><p>必要。用来处理每个送达值。在开始执行后可能执行零次或多次。</p>|
| `error` | <p>Optional. A handler for an error notification. An error halts execution of the observable instance.</p><p> 可选。用来处理错误通知。错误会中断这个可观察对象实例的执行过程。 </p>|
| `complete` | <p>Optional. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.</p><p> 可选。用来处理执行完毕complete通知。当执行完毕后这些值就会继续传给下一个处理器。 </p>|
| `next` | <t>Required. A handler for each delivered value. Called zero or more times after execution starts.</t><t>必要。用来处理每个送达值。在开始执行后可能执行零次或多次。</t>|
| `error` | <t>Optional. A handler for an error notification. An error halts execution of the observable instance.</t><t> 可选。用来处理错误通知。错误会中断这个可观察对象实例的执行过程。 </t>|
| `complete` | <t>Optional. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.</t><t> 可选。用来处理执行完毕complete通知。当执行完毕后这些值就会继续传给下一个处理器。 </t>|
An observer object can define any combination of these handlers. If you don't supply a handler for a notification type, the observer ignores notifications of that type.
@ -107,7 +107,7 @@ In either case, a `next` handler is required. The `error` and `complete` handler
无论哪种情况,`next` 处理器都是必要的,而 `error``complete` 处理器是可选的。
Note that a `next()` function could receive, for instance, message strings, or event objects, numeric values, or structures, depending on context. As a general term, we refer to data published by an observable as a *stream*. Any type of value can be represented with an observable, and the values are published as a stream.
Note that a `next()` function could receive, for instance, message strings, or event objects, numeric values, or stuctures, depending on context. As a general term, we refer to data published by an observable as a *stream*. Any type of value can be represented with an observable, and the values are published as a stream.
注意,`next()` 函数可以接受消息字符串、事件对象、数字值或各种结构,具体类型取决于上下文。
为了更通用一点,我们把由可观察对象发布出来的数据统称为*流*。任何类型的值都可以表示为可观察对象,而这些值会被发布为一个流。
@ -196,12 +196,10 @@ Because observables produce values asynchronously, try/catch will not effectivel
由于可观察对象会异步生成值,所以用 `try/catch` 是无法捕获错误的。你应该在观察者中指定一个 `error` 回调来处理错误。发生错误时还会导致可观察对象清理现有的订阅,并且停止生成值。可观察对象可以生成值(调用 `next` 回调),也可以调用 `complete``error` 回调来主动结束。
<code-example>
myObservable.subscribe({
next(num) { console.log('Next num: ' + num)},
error(err) { console.log('Received an errror: ' + err)}
});
</code-example>
Error handling (and specifically recovering from an error) is covered in more detail in a later section.

View File

@ -32,7 +32,7 @@ Introducing Angular pipes, a way to write display-value transformations that you
You can run the <live-example></live-example> in Stackblitz and download the code from there.
运行<live-example></live-example>来试用本页的代码。
你可以运行<live-example></live-example>,在 Stackblitz 中试用并下载本页的代码。
## Using pipes
@ -249,7 +249,6 @@ Now you need a component to demonstrate the pipe.
现在,你需要一个组件来演示这个管道。
<code-example path="pipes/src/app/power-booster.component.ts" title="src/app/power-booster.component.ts" linenums="false">
</code-example>
<figure>
@ -780,10 +779,8 @@ The list might be sorted by hero `name` and `planet` of origin properties in the
虽然不是很明显,但代码最小化方面也存在风险。想象一个用于英雄列表的排序管道。该列表可能根据英雄原始属性中的 `name``planet` 进行排序,就像这样:
<code-example language="html">
&lt;!-- NOT REAL CODE! -->
&lt;div *ngFor="let hero of heroes | orderBy:'name,planet'">&lt;/div>
</code-example>
You identify the sort fields by text strings, expecting the pipe to reference a property value by indexing
@ -817,5 +814,4 @@ Angular 开发组和一些有经验的 Angular 开发者强烈建议你:把你
If these performance and minification considerations don't apply to you, you can always create your own such pipes
(similar to the [FlyingHeroesPipe](guide/pipes#impure-flying-heroes)) or find them in the community.
如果你不需要顾虑这些性能和最小化问题,也可以创建自己的管道来实现这些功能(参考[FlyingHeroesPipe](guide/pipes#impure-flying-heroes)中的写法)或到社区中去找找。

View File

@ -12,7 +12,7 @@
* Familiarity with [Frequently Used Modules](guide/frequent-ngmodules).
熟悉[常用模块](guide/frequent-ngmodules).
熟悉[常用模块](guide/frequent-ngmodules)
For the final sample app using the provider that this page describes,
see the <live-example></live-example>.
@ -45,7 +45,6 @@ of the file and adding it to the `providers` array:
这将会创建一个名叫 `UserService` 的服务。你现在要让该服务在你的应用注入器中可用,就要修改 `app.module.ts` 文件。先在文件的顶部导入它,然后把它加入 `providers` 数组中:
<code-example path="providers/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
</code-example>
## Provider scope
@ -101,7 +100,6 @@ the same module cant access it.)
在组件中提供服务,会限定该服务只能在该组件中有效(同一模块中的其它组件不能访问它)。
<code-example path="providers/src/app/app.component.ts" region="component-providers" title="src/app/app.component.ts" linenums="false">
</code-example>
## Providing services in modules vs. components
@ -132,7 +130,7 @@ Register a provider with a component when you must limit a service instance to a
You may also be interested in:
你可能对下列内容感兴趣:
可能对下列内容感兴趣:
* [Singleton Services](guide/singleton-services), which elaborates on the concepts covered on this page.
@ -140,7 +138,7 @@ You may also be interested in:
* [Lazy Loading Modules](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules)
* [NgModule FAQ](guide/ngmodule-faq).

View File

@ -59,7 +59,6 @@ Then **install the [Angular CLI](https://github.com/angular/angular-cli)** globa
然后全局安装 **[Angular CLI](https://github.com/angular/angular-cli)** 。
<code-example language="sh" class="code-shell">
npm install -g @angular/cli
</code-example>
@ -77,7 +76,6 @@ Generate a new project and skeleton application by running the following command
运行下列命令来生成一个新项目以及应用的骨架代码:
<code-example language="sh" class="code-shell">
ng new my-app
</code-example>
@ -101,10 +99,8 @@ Go to the project directory and launch the server.
进入项目目录,并启动服务器。
<code-example language="sh" class="code-shell">
cd my-app
ng serve --open
</code-example>
The `ng serve` command launches the server, watches your files,
@ -282,7 +278,6 @@ Any files outside of this folder are meant to support building your app.
</col>
<col width="80%">
</col>
<tr>
<th>
@ -302,7 +297,6 @@ Any files outside of this folder are meant to support building your app.
</th>
</tr>
<tr>
<td>
@ -323,7 +317,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -345,7 +338,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -364,7 +356,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -385,14 +376,13 @@ Any files outside of this folder are meant to support building your app.
这个文件夹中包括为各个目标环境准备的文件,它们导出了一些应用中要用到的配置变量。
这些文件会在构建应用时被替换。
比如你可能在产环境中使用不同的 API 端点地址,或使用不同的统计 Token 参数。
比如你可能在产环境中使用不同的 API 端点地址,或使用不同的统计 Token 参数。
甚至使用一些模拟服务。
所有这些CLI 都替你考虑到了。
</td>
</tr>
<tr>
<td>
@ -412,7 +402,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -435,7 +424,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -459,7 +447,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -482,7 +469,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -503,7 +489,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -524,7 +509,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
<tr>
<td>
@ -543,7 +527,6 @@ Any files outside of this folder are meant to support building your app.
</td>
</tr>
</table>
### The root folder
@ -610,7 +593,6 @@ These files go in the root folder next to `src/`.
</col>
<col width="80%">
</col>
<tr>
<th>
@ -625,12 +607,11 @@ These files go in the root folder next to `src/`.
Purpose
目的
用途
</th>
</tr>
<tr>
<td>
@ -653,7 +634,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -672,7 +652,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -695,7 +674,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -717,7 +695,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -735,7 +712,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -754,7 +730,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -774,7 +749,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -793,7 +767,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -814,7 +787,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -832,7 +804,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
<tr>
<td>
@ -853,7 +824,6 @@ These files go in the root folder next to `src/`.
</td>
</tr>
</table>
<div class="l-sub-section">

View File

@ -1156,7 +1156,6 @@ which is covered in the section on [`FormArray`](guide/reactive-forms#form-array
`Hero` 有一个住址数组。这个表单模型只表示了一个住址,稍后的 [`FormArray`] (guide/reactive-forms#form-array "Form arrays")则可以表示多个。
Keeping the two models close in shape facilitates copying the data model properties
to the form model with the `patchValue()` and `setValue()` methods in the next section.

View File

@ -214,7 +214,6 @@ _after_ a `RouterOutlet` that you've placed in the host view's HTML.
有了这份配置,当本应用在浏览器中的 URL 变为 `/heroes` 时,路由器就会匹配到 `path``heroes``Route`,并在宿主视图中的*`RouterOutlet`*之后显示 `HeroListComponent` 组件。
<code-example language="html">
&lt;router-outlet>&lt;/router-outlet>
&lt;!-- Routed views go here -->
@ -294,7 +293,6 @@ It has a great deal of useful information including:
它有一大堆有用的信息,包括:
<table>
<tr>
<th>
@ -496,7 +494,6 @@ It has a great deal of useful information including:
</td>
</tr>
</table>
<div class="l-sub-section">
@ -525,7 +522,6 @@ During each navigation, the `Router` emits navigation events through the `Router
在每次导航中,`Router` 都会通过 `Router.events` 属性发布一些导航事件。这些事件的范围涵盖了从开始导航到结束导航之间的很多时间点。下表中列出了全部导航事件:
<table>
<tr>
<th>
@ -674,7 +670,6 @@ During each navigation, the `Router` emits navigation events through the `Router
</td>
</tr>
</table>
These events are logged to the console when the `enableTracing` option is enabled also. Since the events are provided as an `Observable`, you can `filter()` for events of interest and `subscribe()` to them to make decisions based on the sequence of events in the navigation process.
@ -748,8 +743,6 @@ Here are the key `Router` terms and their meanings:
<code>RouterModule</code>
<code>RouterModule</code>(路由器模块)
</td>
<td>
@ -1218,7 +1211,6 @@ That's why the example code replaces the `<base href...>` with a script that wri
这就是为什么范例代码中要用一个脚本动态写入 `<base>` 标签,而不是直接写 `<base href...>`
<code-example language="html">
&lt;script>document.write('&lt;base href="' + document.location + '" />');&lt;/script>
</code-example>
@ -1344,7 +1336,7 @@ The corresponding component template looks like this:
### *RouterOutlet*
### *RouterOutlet* 指令
### 路由出口
The `RouterOutlet` is a directive from the router library that marks
the spot in the template where the router should display the views for that outlet.
@ -1525,9 +1517,7 @@ When the application launches, the initial URL in the browser bar is something l
应用启动时,浏览器地址栏中的初始 URL 是这样的:
<code-example>
localhost:3000
</code-example>
That doesn't match any of the concrete configured routes which means
@ -1560,7 +1550,6 @@ It's just above the wildcard route in the following excerpt showing the complete
在下方的代码片段中,它出现在通配符路由的紧上方,展示了这个里程碑的完整 `appRoutes`
<code-example path="router/src/app/app-routing.module.1.ts" linenums="false" title="src/app/app-routing.module.ts (appRoutes)" region="appRoutes">
</code-example>
A redirect route requires a `pathMatch` property to tell the router how to match a URL to the path of a route.
@ -2361,7 +2350,6 @@ you expect a hero id to appear in the browser URL like this:
如果要告诉路由器导航到详情组件并让它显示“Magneta”你会期望这个英雄的 `id` 像这样显示在浏览器的 URL 中:
<code-example format="nocode">
localhost:3000/hero/15
</code-example>
@ -2505,7 +2493,6 @@ to handle parameter access for both route parameters (`paramMap`) and query para
`ParamMap` API 是参照[URLSearchParams 接口](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)来设计的。它提供了一些方法来处理对路由参数(`paramMap`)和查询参数(`queryParamMap`)中的参数访问。
<table>
<tr>
<th>
@ -2597,7 +2584,6 @@ to handle parameter access for both route parameters (`paramMap`) and query para
</td>
</tr>
</table>
{@a reuse}
@ -2745,7 +2731,6 @@ as you do when navigating to the `HeroDetailComponent` in order to view the hero
如果想导航到 `HeroDetailComponent` 以对 id 为 15 的英雄进行查看并编辑,就要在路由的 URL 中使用[*路由参数*](guide/router#route-parameters)来指定*必要*参数值。
<code-example format="nocode">
localhost:3000/hero/15
</code-example>
@ -2866,7 +2851,6 @@ It should look something like this, depending on where you run it:
它应该是这样的,不过也取决于你在哪里运行它:
<code-example language="bash">
localhost:3000/heroes;id=15;foo=foo
</code-example>
@ -3413,7 +3397,6 @@ Add the following `crisis-center.component.ts` to the `crisis-center` folder:
`crisis-center` 目录下添加下列 `crisis-center.component.ts` 文件:
<code-example path="router/src/app/crisis-center/crisis-center.component.ts" linenums="false" title="src/app/crisis-center/crisis-center.component.ts">
</code-example>
The `CrisisCenterComponent` has the following in common with the `AppComponent`:
@ -3455,7 +3438,6 @@ As a host page for the "Crisis Center" feature, add the following `crisis-center
把下面这个 `crisis-center-home.component.ts` 添加到 `crisis-center` 目录下,作为 "危机中心" 特性区的宿主页面。
<code-example path="router/src/app/crisis-center/crisis-center-home.component.ts" linenums="false" title="src/app/crisis-center/crisis-center-home.component.ts" >
</code-example>
Create a `crisis-center-routing.module.ts` file as you did the `heroes-routing.module.ts` file.
@ -3465,7 +3447,6 @@ This time, you define **child routes** *within* the parent `crisis-center` route
但这次,你要把**子路由**定义在父路由 `crisis-center` 中。
<code-example path="router/src/app/crisis-center/crisis-center-routing.module.1.ts" linenums="false" title="src/app/crisis-center/crisis-center-routing.module.ts (Routes)" region="routes">
</code-example>
Notice that the parent `crisis-center` route has a `children` property
@ -3529,7 +3510,6 @@ The absolute URL for the latter example, including the `localhost` origin, is
本例子中包含站点部分的绝对 URL就是
<code-example>
localhost:3000/crisis-center/2
</code-example>
@ -3882,7 +3862,6 @@ you should see something like the following URL in the browser address bar.
导航到*危机中心*并点击“Contact”你将会在浏览器的地址栏看到如下 URL
<code-example>
http://.../crisis-center(popup:compose)
</code-example>
@ -3908,9 +3887,7 @@ Click the _Heroes_ link and look at the URL again.
点击 *Heroes* 链接,并再次查看 URL
<code-example>
http://.../heroes(popup:compose)
</code-example>
The primary navigation part has changed; the secondary route is the same.
@ -5723,7 +5700,6 @@ Here's the *Crisis Center* URL in this "HTML5 pushState" style:
下面是*危机中心*的 URL 在“HTML 5 pushState”风格下的样子
<code-example format="nocode">
localhost:3002/crisis-center/
</code-example>
@ -5736,7 +5712,6 @@ URLs with hashes. Here's a "hash URL" that routes to the *Crisis Center*.
老旧的浏览器在当前地址的 URL 变化时总会往服务器发送页面请求……唯一的例外规则是:当这些变化位于“#”被称为“hash”后面时不会发送。通过把应用内的路由 URL 拼接在 `#` 之后,路由器可以获得这条“例外规则”带来的优点。下面是到*危机中心*路由的“hash URL”
<code-example format="nocode">
localhost:3002/src/#/crisis-center/
</code-example>

View File

@ -15,7 +15,7 @@ For more information about the attacks and mitigations described below, see [OWA
You can run the <live-example></live-example> in Stackblitz and download the code from there.
运行<live-example></live-example>来试用本页的代码。
你可以运行<live-example></live-example>,在 Stackblitz 中试用并下载本页的代码。
<h2 id='report-issues'>Reporting vulnerabilities</h2>
@ -426,6 +426,5 @@ must be audited as such. Angular-specific APIs that should be audited in a secur
such as the [_bypassSecurityTrust_](guide/security#bypass-security-apis) methods, are marked in the documentation
as security sensitive.
Angular 应用应该遵循和常规 Web 应用一样的安全原则并按照这些原则进行审计。Angular 中某些应该在安全评审中被审计的 API
比如[_bypassSecurityTrust_](guide/security#bypass-security-apis) API都在文档中被明确标记为安全性敏感的。

View File

@ -16,7 +16,7 @@ A basic understanding of the following:
* [Getting Started with Service Workers](guide/service-worker-getting-started).
[Service Worker 快速起步](guide/service-worker-getting-started).
[Service Worker 快速起步](guide/service-worker-getting-started)
<hr />
@ -101,8 +101,8 @@ Doing this could break lazy-loading into currently running apps, especially if t
You may also be interested in the following:
你可能对下列内容感兴趣:
你可能对下列内容感兴趣:
* [Service Worker in Production](guide/service-worker-devops).
[环境下的 Service Worker](guide/service-worker-devops).
[产环境下的 Service Worker](guide/service-worker-devops)

View File

@ -14,7 +14,7 @@ A basic understanding of the following:
* [Service Worker in Production](guide/service-worker-devops).
[环境下的 Service Worker](guide/service-worker-devops).
[产环境下的 Service Worker](guide/service-worker-devops)
<hr />
@ -314,4 +314,3 @@ Angular Service Worker 可以使用两种缓存策略之一来获取数据资源
* `freshness` optimizes for currency of data, preferentially fetching requested data from the network. Only if the network times out, according to `timeout`, does the request fall back to the cache. This is useful for resources that change frequently; for example, account balances.
`freshness` 为数据的即时性而优化,优先从网络获取请求的数据。只有当网络超时时,请求才会根据 `timeout` 的设置回退到缓存中。这对于那些频繁变化的资源很有用,例如账户余额。

View File

@ -1,11 +1,11 @@
# Service worker in production
# 产环境下的 Service Worker
# 产环境下的 Service Worker
This page is a reference for deploying and supporting production apps that use the Angular service worker. It explains how the Angular service worker fits into the larger production environment, the service worker's behavior under various conditions, and available recourses and fail-safes.
本页讲的是如何使用 Angular Service Worker 发布和支持产环境下的应用。
它解释了 Angular Service Worker 如何满足大规模产环境的需求、Service Worker 在多种条件下有哪些行为以及有哪些可用的资源和故障保护机制。
本页讲的是如何使用 Angular Service Worker 发布和支持产环境下的应用。
它解释了 Angular Service Worker 如何满足大规模产环境的需求、Service Worker 在多种条件下有哪些行为以及有哪些可用的资源和故障保护机制。
#### Prerequisites
@ -557,8 +557,8 @@ the past on your site.
You may also be interested in the following:
你可能对下列内容感兴趣:
你可能对下列内容感兴趣:
* [Service Worker Configuration](guide/service-worker-config).
[Service Worker 配置](guide/service-worker-config).
[Service Worker 配置](guide/service-worker-config)

View File

@ -120,7 +120,7 @@ At the top of the root module, `src/app/app.module.ts`, import `ServiceWorkerMod
Add `ServiceWorkerModule` to the `@NgModule` `imports` array. Use the `register()` helper to take care of registering the service worker, taking care to disable the service worker when not running in production mode.
`ServiceWorkerModule` 添加到 `@NgModule``imports` 数组中。使用 `register()` 来帮助管理 Service Worker 的注册并在非产环境下运行时禁用 Service Worker。
`ServiceWorkerModule` 添加到 `@NgModule``imports` 数组中。使用 `register()` 来帮助管理 Service Worker 的注册并在非产环境下运行时禁用 Service Worker。
<code-example path="service-worker-getting-started/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts" region="sw-module"> </code-example>
@ -367,8 +367,8 @@ Service Worker *在后台*安装好了这个更新后的版本,下次加载或
You may also be interested in the following:
你可能对下列内容感兴趣:
你可能对下列内容感兴趣:
* [Communicating with service workers](guide/service-worker-communications).
[与 Service Worker 通讯](guide/service-worker-communications).
[与 Service Worker 通讯](guide/service-worker-communications)

View File

@ -122,8 +122,8 @@ The remainder of this Angular documentation specifically addresses the Angular i
You may also be interested in the following:
你可能还对下列内容感兴趣:
你可能还对下列内容感兴趣:
* [Getting Started with service workers](guide/service-worker-getting-started).
[Service Worker 快速起步](guide/service-worker-getting-started).
[Service Worker 快速起步](guide/service-worker-getting-started)

View File

@ -22,9 +22,7 @@ The obvious approach is to bind a property of the component to the HTML `<title>
显而易见的方法是把组件的属性绑定到 HTML 的 `<title>` 标签上,像这样:
<code-example format=''>
&lt;title&gt;{{This_Does_Not_Work}}&lt;/title&gt;
</code-example>
Sorry but that won't work.
@ -89,11 +87,9 @@ Here's the complete solution:
这里是完整的方案(代码)。
<code-tabs>
<code-pane title="src/main.ts" path="set-document-title/src/main.ts"></code-pane>
<code-pane title="src/app/app.module.ts" path="set-document-title/src/app/app.module.ts"></code-pane>
<code-pane title="src/app/app.component.ts" path="set-document-title/src/app/app.component.ts"></code-pane>
</code-tabs>
## Why provide the `Title` service in `bootstrap`
@ -116,5 +112,4 @@ you'll have to provide a different `Title` service that understands
the concept of a "document title" for that specific platform.
Ideally, the application itself neither knows nor cares about the runtime environment.
你的做法正是如此。这里的 `Title` 服务是 Angular*浏览器平台*的一部分。如果在其它平台上引导应用程序,就得提供另一个专为那个平台准备的 `Title` 服务。

View File

@ -394,9 +394,7 @@ If you do, this page can help you understand their purpose.
**SystemJS** 模块加载器指定去哪儿查找在 JavaScript 的 `import` 语句中引用的模块。例如:
<code-example language="ts">
import { Component } from '@angular/core;
</code-example>
Don't touch this file unless you are fully versed in SystemJS configuration.

View File

@ -32,7 +32,6 @@ Perform the _clone-to-launch_ steps with these terminal commands.
运行下列命令来执行*克隆并启动*步骤。
<code-example language="sh" class="code-shell">
git clone https://github.com/angular/quickstart.git quickstart
cd quickstart
npm install
@ -61,7 +60,6 @@ and unzip it into your project folder. Then perform the remaining steps with the
并解压到你的项目目录中。然后执行下面的命令完成剩余步骤。
<code-example language="sh" class="code-shell">
cd quickstart
npm install
npm start
@ -103,7 +101,6 @@ Open a terminal window in the project folder and enter the following commands fo
### OS/X (bash)
<code-example language="sh" class="code-shell">
xargs rm -rf &lt; non-essential-files.osx.txt
rm src/app/*.spec*.ts
rm non-essential-files.osx.txt
@ -113,7 +110,6 @@ Open a terminal window in the project folder and enter the following commands fo
### Windows
<code-example language="sh" class="code-shell">
for /f %i in (non-essential-files.txt) do del %i /F /S /Q
rd .git /s /q
rd e2e /s /q

View File

@ -28,7 +28,7 @@ A basic understanding of the following:
* [Lazy loading modules](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules)
<!--* Components (#TBD) We dont have a page just on the concept of components, but I think one would be helpful for beginners.-->
@ -123,12 +123,12 @@ To read about sharing services, see [Providers](guide/providers).
You may also be interested in the following:
你可能还对下列内容感兴趣:
你可能还对下列内容感兴趣:
* [Providers](guide/providers).
[提供商](guide/providers)。
[服务提供商](guide/providers)。
* [Types of Feature Modules](guide/module-types).
[特性模块的分类](guide/module-types).
[特性模块的分类](guide/module-types)

View File

@ -44,7 +44,6 @@ a way of providing services from a designated NgModule.
下面的范例模块习惯上叫做 `CoreModule`。`@NgModule` 用来创建结构良好的基础设施,让你能够在一个指定的模块中提供服务。
<code-example path="ngmodules/src/app/core/core.module.ts" region="user-service" title="src/app/core/core.module.ts" linenums="false">
</code-example>
Here, `CoreModule` provides the `UserService`, and because `AppModule`
@ -269,7 +268,6 @@ Here are the two files in their entirety for reference:
以下这两个文件仅供参考:
<code-tabs linenums="false">
<code-pane
title="app.module.ts"
path="ngmodules/src/app/app.module.ts">
@ -279,7 +277,6 @@ Here are the two files in their entirety for reference:
region="whole-core-module"
path="ngmodules/src/app/core/core.module.ts">
</code-pane>
</code-tabs>
<hr>
@ -298,7 +295,7 @@ You may also be interested in:
* [Lazy Loading Modules](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules).
[惰性加载模块](guide/lazy-loading-ngmodules)
* [NgModule FAQ](guide/ngmodule-faq).

View File

@ -723,7 +723,6 @@ It's more like the curly braces in a JavaScript `if`-block:
它不是一个指令、组件、类或接口,更像是 JavaScript 中 `if` 块中的花括号。
<code-example language="javascript">
if (someCondition) {
statement1;
statement2;

View File

@ -509,10 +509,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Component({ ... })
export class AppComponent { }
</code-example>
</td>
@ -530,10 +528,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Component({ ... })
export class HeroesComponent { }
</code-example>
</td>
@ -551,10 +547,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Component({ ... })
export class HeroListComponent { }
</code-example>
</td>
@ -572,10 +566,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Component({ ... })
export class HeroDetailComponent { }
</code-example>
</td>
@ -593,10 +585,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Directive({ ... })
export class ValidationDirective { }
</code-example>
</td>
@ -614,10 +604,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class AppModule
</code-example>
</td>
@ -635,10 +623,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Pipe({ name: 'initCaps' })
export class InitCapsPipe implements PipeTransform { }
</code-example>
</td>
@ -656,10 +642,8 @@ and reference assets of different types.
<td>
<code-example hideCopy class="no-box">
@Injectable()
export class UserProfileService { }
</code-example>
</td>
@ -775,10 +759,8 @@ As always, strive for consistency.
<td>
<code-example hideCopy class="no-box">
@Injectable()
export class HeroDataService { }
</code-example>
</td>
@ -796,10 +778,8 @@ As always, strive for consistency.
<td>
<code-example hideCopy class="no-box">
@Injectable()
export class CreditService { }
</code-example>
</td>
@ -817,10 +797,8 @@ As always, strive for consistency.
<td>
<code-example hideCopy class="no-box">
@Injectable()
export class Logger { }
</code-example>
</td>
@ -1126,10 +1104,8 @@ For example, the prefix `toh` represents from **T**our **o**f **H**eroes and the
<td>
<code-example hideCopy class="no-box">
@Pipe({ name: 'ellipsis' })
export class EllipsisPipe implements PipeTransform { }
</code-example>
</td>
@ -1147,10 +1123,8 @@ For example, the prefix `toh` represents from **T**our **o**f **H**eroes and the
<td>
<code-example hideCopy class="no-box">
@Pipe({ name: 'initCaps' })
export class InitCapsPipe implements PipeTransform { }
</code-example>
</td>
@ -1520,10 +1494,8 @@ A consistent class and file name convention make these modules easy to spot and
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class AppModule { }
</code-example>
</td>
@ -1541,10 +1513,8 @@ A consistent class and file name convention make these modules easy to spot and
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class HeroesModule { }
</code-example>
</td>
@ -1562,10 +1532,8 @@ A consistent class and file name convention make these modules easy to spot and
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class VillainsModule { }
</code-example>
</td>
@ -1583,10 +1551,8 @@ A consistent class and file name convention make these modules easy to spot and
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class AppRoutingModule { }
</code-example>
</td>
@ -1604,10 +1570,8 @@ A consistent class and file name convention make these modules easy to spot and
<td>
<code-example hideCopy class="no-box">
@NgModule({ ... })
export class HeroesRoutingModule { }
</code-example>
</td>
@ -4667,5 +4631,4 @@ Useful tools and tips for Angular.
<a href="#toc">Back to top</a>
<a href="#toc">回到顶部</a>

View File

@ -75,7 +75,6 @@ You met the double-curly braces of interpolation, `{{` and `}}`, early in your A
在以前的 Angular 教程中,你遇到过由双花括号括起来的插值表达式,`{{` 和 `}}`
<code-example path="template-syntax/src/app/app.component.html" region="first-interpolation" title="src/app/app.component.html" linenums="false">
</code-example>
You use interpolation to weave calculated strings into the text between HTML element tags and within attribute assignments.
@ -83,7 +82,6 @@ You use interpolation to weave calculated strings into the text between HTML ele
插值表达式可以把计算后的字符串插入到 HTML 元素标签内的文本或对标签的属性进行赋值。
<code-example path="template-syntax/src/app/app.component.html" region="title+image" title="src/app/app.component.html" linenums="false">
</code-example>
The text between the braces is often the name of a component property. Angular replaces that name with the
@ -101,7 +99,6 @@ and then **converts to a string**. The following interpolation illustrates the p
下列插值表达式通过把括号中的两个数字相加说明了这一点:
<code-example path="template-syntax/src/app/app.component.html" region="sum-1" title="src/app/app.component.html" linenums="false">
</code-example>
The expression can invoke methods of the host component such as `getVal()`, seen here:
@ -109,7 +106,6 @@ The expression can invoke methods of the host component such as `getVal()`, seen
这个表达式可以调用宿主组件的方法,就像下面用的 `getVal()`
<code-example path="template-syntax/src/app/app.component.html" region="sum-2" title="src/app/app.component.html" linenums="false">
</code-example>
Angular evaluates all expressions in double curly braces,
@ -178,7 +174,7 @@ JavaScript 中那些具有或可能引发副作用的表达式是被禁止的,
* increment and decrement operators (`++` and `--`)
自增或自减操作符 (`++` 和 `--`)
自增和自减运算符:`++` 和 `--`
Other notable differences from JavaScript syntax include:
@ -206,7 +202,6 @@ In the following snippets, the `title` within double-curly braces and the
在下面的代码片段中,双花括号中的 `title` 和引号中的 `isUnchanged` 所引用的都是 `AppComponent` 中的属性。
<code-example path="template-syntax/src/app/app.component.html" region="context-component-expression" title="src/app/app.component.html" linenums="false">
</code-example>
An expression may also refer to properties of the _template's_ context
@ -217,7 +212,6 @@ or a [template reference variable](guide/template-syntax#ref-vars) (`#heroInput`
比如[模板输入变量](guide/template-syntax#template-input-variable) (`let hero`)和[模板引用变量](guide/template-syntax#ref-vars)(`#heroInput`)就是备选的上下文对象之一。
<code-example path="template-syntax/src/app/app.component.html" region="context-var" title="src/app/app.component.html" linenums="false">
</code-example>
The context for terms in an expression is a blend of the _template variables_,
@ -368,7 +362,6 @@ appearing in quotes to the right of the `=`&nbsp;symbol as in `(event)="statemen
模板语句将在[事件绑定](guide/template-syntax#event-binding)一节看到,它出现在 `=` 号右侧的引号中,就像这样:`(event)="statement"`。
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" title="src/app/app.component.html" linenums="false">
</code-example>
A template statement *has a side effect*.
@ -432,7 +425,6 @@ The *deleteHero* in `(click)="deleteHero()"` is a method of the data-bound compo
`(click)="deleteHero()"` 中的 *deleteHero* 就是这个数据绑定组件上的一个方法。
<code-example path="template-syntax/src/app/app.component.html" region="context-component-statement" title="src/app/app.component.html" linenums="false">
</code-example>
The statement context may also refer to properties of the template's own context.
@ -445,7 +437,6 @@ are passed to an event handling method of the component.
在下面的例子中,就把模板的 `$event` 对象、[模板输入变量](guide/template-syntax#template-input-variable) (`let hero`)和[模板引用变量](guide/template-syntax#ref-vars) (`#heroForm`)传给了组件中的一个事件处理器方法。
<code-example path="template-syntax/src/app/app.component.html" region="context-var-statement" title="src/app/app.component.html" linenums="false">
</code-example>
Template context names take precedence over component context names.
@ -518,7 +509,6 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
</col>
<col width="20%">
</col>
<tr>
<th>
@ -546,7 +536,6 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
</th>
</tr>
<tr>
<td>
@ -560,11 +549,9 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
<td>
<code-example>
{{expression}}
[target]="expression"
bind-target="expression"
</code-example>
</td>
@ -598,10 +585,8 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
<td>
<code-example>
(target)="statement"
on-target="statement"
</code-example>
</td>
@ -615,7 +600,6 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
</td>
</tr>
<tr>
<td>
@ -629,10 +613,8 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
<td>
<code-example>
[(target)]="expression"
bindon-target="expression"
</code-example>
</td>
@ -646,9 +628,7 @@ from the _source-to-view_, from _view-to-source_, and in the two-way sequence: _
</td>
</tr>
</tr>
</table>
@ -704,7 +684,6 @@ you modify those elements by setting element attributes with string constants.
通过把字符串常量设置到元素的 attribute 来修改那些元素。
<code-example path="template-syntax/src/app/app.component.html" region="img+button" title="src/app/app.component.html" linenums="false">
</code-example>
You still create a structure and initialize attribute values this way in Angular templates.
@ -717,7 +696,6 @@ and drop them into templates as if they were native HTML elements.
然后,用封装了 HTML 的组件创建新元素,并把它们当作原生 HTML 元素在模板中使用。
<code-example path="template-syntax/src/app/app.component.html" region="hero-detail-1" title="src/app/app.component.html" linenums="false">
</code-example>
That's HTML Plus.
@ -729,7 +707,6 @@ Then you learn about data binding. The first binding you meet might look like th
现在开始学习数据绑定。你碰到的第一种数据绑定是这样的:
<code-example path="template-syntax/src/app/app.component.html" region="disabled-button-1" title="src/app/app.component.html" linenums="false">
</code-example>
You'll get to that peculiar bracket notation in a moment. Looking beyond it,
@ -880,7 +857,6 @@ The following table summarizes:
</col>
<col width="75%">
</col>
<tr>
<th>
@ -908,7 +884,6 @@ The following table summarizes:
</th>
</tr>
<tr>
<td>
@ -934,13 +909,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
<tr>
<td>
@ -966,13 +939,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
<tr>
<td>
@ -994,13 +965,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
<tr>
<td>
@ -1021,13 +990,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
<tr>
<td>
@ -1047,13 +1014,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
<tr>
<td>
@ -1073,13 +1038,11 @@ The following table summarizes:
<td>
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-syntax-1" title="src/app/app.component.html" linenums="false">
</code-example>
</td>
</tr>
</table>
With this broad view in mind, you're ready to look at binding types in detail.
@ -1106,7 +1069,6 @@ binding the `src` property of an image element to a component's `heroImageUrl` p
下面这个例子中image 元素的 `src` 属性会被绑定到组件的 `heroImageUrl` 属性上:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
Another example is disabling a button when the component says that it `isUnchanged`:
@ -1114,7 +1076,6 @@ Another example is disabling a button when the component says that it `isUnchang
另一个例子是当组件说它 `isUnchanged`(未改变)时禁用按钮:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-2" title="src/app/app.component.html" linenums="false">
</code-example>
Another is setting a property of a directive:
@ -1122,7 +1083,6 @@ Another is setting a property of a directive:
另一个例子是设置指令的属性:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-3" title="src/app/app.component.html" linenums="false">
</code-example>
Yet another is setting the model property of a custom component (a great way
@ -1131,7 +1091,6 @@ for parent and child components to communicate):
还有另一个例子是设置自定义组件的模型属性(这是父子组件之间通讯的重要途径):
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-4" title="src/app/app.component.html" linenums="false">
</code-example>
### One-way *in*
@ -1181,7 +1140,6 @@ The target property in the following code is the image element's `src` property.
包裹在方括号中的元素属性名标记着目标属性。下列代码中的目标属性是 image 元素的 `src` 属性。
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
Some people prefer the `bind-` prefix alternative, known as the *canonical form*:
@ -1189,7 +1147,6 @@ Some people prefer the `bind-` prefix alternative, known as the *canonical form*
有些人喜欢用 `bind-` 前缀的可选形式,并称之为*规范形式*
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-5" title="src/app/app.component.html" linenums="false">
</code-example>
The target name is always the name of a property, even when it appears to be the name of something else.
@ -1205,7 +1162,6 @@ as it is in the following example:
元素属性可能是最常见的绑定目标,但 Angular 会先去看这个名字是否是某个已知指令的属性名,就像下面的例子中一样:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-3" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -1269,7 +1225,6 @@ The `hero` property of the `HeroDetail` component expects a `Hero` object, which
`HeroDetail` 组件的 `hero` 属性想要一个 `Hero` 对象,那就在属性绑定中精确地给它一个 `Hero` 对象:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-4" title="src/app/app.component.html" linenums="false">
</code-example>
### Remember the brackets
@ -1290,7 +1245,6 @@ Don't make the following mistake:
不要出现这样的失误:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-6" title="src/app/app.component.html" linenums="false">
</code-example>
{@a one-time-initialization}
@ -1324,7 +1278,6 @@ not a template expression. Angular sets it and forgets about it.
下面这个例子把 `HeroDetailComponent``prefix` 属性初始化为固定的字符串而不是模板表达式。Angular 设置它,然后忘记它。
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-7" title="src/app/app.component.html" linenums="false">
</code-example>
The `[hero]` binding, on the other hand, remains a live binding to the component's `currentHero` property.
@ -1344,7 +1297,6 @@ The following binding pairs do the same thing:
下列这几对绑定做的事情完全相同:
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-vs-interpolation" title="src/app/app.component.html" linenums="false">
</code-example>
_Interpolation_ is a convenient alternative to _property binding_ in many cases.
@ -1375,7 +1327,6 @@ Imagine the following *malicious content*.
假设下面的*恶意内容*
<code-example path="template-syntax/src/app/app.component.ts" region="evil-title" title="src/app/app.component.ts" linenums="false">
</code-example>
Fortunately, Angular data binding is on alert for dangerous HTML.
@ -1388,7 +1339,6 @@ nor property binding.
不管是插值表达式还是属性绑定,都**不会**允许带有 script 标签的 HTML 泄漏到浏览器中。
<code-example path="template-syntax/src/app/app.component.html" region="property-binding-vs-interpolation-sanitization" title="src/app/app.component.html" linenums="false">
</code-example>
Interpolation handles the script tags differently than property binding but both approaches render the
@ -1453,9 +1403,7 @@ This fact becomes painfully obvious when you write something like this.
如果想写出类似下面这样的东西,就会暴露出痛点了:
<code-example language="html">
&lt;tr&gt;&lt;td colspan="{{1 + 1}}"&gt;Three-Four&lt;/td&gt;&lt;/tr&gt;
</code-example>
And you get this error:
@ -1463,10 +1411,8 @@ And you get this error:
会得到这个错误:
<code-example format="nocode">
Template parse errors:
Can't bind to 'colspan' since it isn't a known native property
</code-example>
As the message says, the `<td>` element does not have a `colspan` property.
@ -1494,7 +1440,6 @@ Bind `[attr.colspan]` to a calculated value:
这里把 `[attr.colspan]` 绑定到一个计算值:
<code-example path="template-syntax/src/app/app.component.html" region="attrib-binding-colspan" title="src/app/app.component.html" linenums="false">
</code-example>
Here's how the table renders:
@ -1517,16 +1462,10 @@ Here's how the table renders:
<td>
Five
Five</td><td>Six
</td>
<td>
Six
</td>
</tr>
</table>
@ -1538,7 +1477,6 @@ attribute 绑定的主要用例之一是设置 ARIA attribute译注ARIA
就像这个例子中一样:
<code-example path="template-syntax/src/app/app.component.html" region="attrib-binding-aria" title="src/app/app.component.html" linenums="false">
</code-example>
<hr/>
@ -1566,7 +1504,6 @@ with class bindings. Here's how to set the attribute without binding:
下列例子示范了如何通过 CSS 类绑定来添加和移除应用的 "special" 类。不用绑定直接设置 attribute 时是这样的:
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
You can replace that with a binding to a string of the desired class names; this is an all-or-nothing, replacement binding.
@ -1575,7 +1512,6 @@ You can replace that with a binding to a string of the desired class names; this
(译注:即当 badCurly 有值时 class 这个 attribute 设置的内容会被完全覆盖)
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-2" title="src/app/app.component.html" linenums="false">
</code-example>
Finally, you can bind to a specific class name.
@ -1586,7 +1522,6 @@ It removes the class when the expression is falsy.
当模板表达式的求值结果是真值时Angular 会添加这个类,反之则移除它。
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-3" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -1617,7 +1552,6 @@ followed by a dot (`.`) and the name of a CSS style property: `[style.style-prop
形如:`[style.style-property]`。
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
Some style binding styles have a unit extension.
@ -1626,7 +1560,6 @@ The following example conditionally sets the font size in “em” and “%”
有些样式绑定中的样式带有单位。在这里,以根据条件用 “em” 和 “%” 来设置字体大小的单位。
<code-example path="template-syntax/src/app/app.component.html" region="style-binding-2" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -1685,7 +1618,6 @@ the component's `onSave()` method whenever a click occurs:
下面事件绑定监听按钮的点击事件。每当点击发生时,都会调用组件的 `onSave()` 方法。
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
### Target event
@ -1698,7 +1630,6 @@ identifies the target event. In the following example, the target is the button'
**圆括号中的名称** —— 比如 `(click)` —— 标记出目标事件。在下面例子中,目标是按钮的 click 事件。
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
Some people prefer the `on-` prefix alternative, known as the **canonical form**:
@ -1706,7 +1637,6 @@ Some people prefer the `on-` prefix alternative, known as the **canonical form**
有些人更喜欢带 `on-` 前缀的备选形式,称之为**规范形式**
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-2" title="src/app/app.component.html" linenums="false">
</code-example>
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
@ -1715,7 +1645,6 @@ of a known directive, as it does in the following example:
元素事件可能是更常见的目标,但 Angular 会先看这个名字是否能匹配上已知指令的事件属性,就像下面这个例子:
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-3" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -1766,7 +1695,6 @@ Consider this example:
考虑这个范例:
<code-example path="template-syntax/src/app/app.component.html" region="without-NgModel" title="src/app/app.component.html" linenums="false">
</code-example>
This code sets the input box `value` property by binding to the `name` property.
@ -1818,11 +1746,9 @@ Here are the pertinent excerpts from that `HeroDetailComponent`:
下面的代码节选自 `HeroDetailComponent`
<code-example path="template-syntax/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (template)" region="template-1">
</code-example>
<code-example path="template-syntax/src/app/hero-detail.component.ts" linenums="false" title="src/app/hero-detail.component.ts (deleteRequest)" region="deleteRequest">
</code-example>
The component defines a `deleteRequest` property that returns an `EventEmitter`.
@ -1837,7 +1763,6 @@ Now imagine a hosting parent component that binds to the `HeroDetailComponent`'s
现在,假设有个宿主的父组件,它绑定了 `HeroDetailComponent``deleteRequest` 事件。
<code-example path="template-syntax/src/app/app.component.html" linenums="false" title="src/app/app.component.html (event-binding-to-component)" region="event-binding-to-component">
</code-example>
When the `deleteRequest` event fires, Angular calls the parent component's `deleteHero` method,
@ -1908,7 +1833,6 @@ It has a `size` value property and a companion `sizeChange` event:
下面的 `SizerComponent` 符合这个模式。它有 `size` 属性和伴随的 `sizeChange` 事件:
<code-example path="template-syntax/src/app/sizer.component.ts" title="src/app/sizer.component.ts">
</code-example>
The initial `size` is an input value from a property binding.
@ -1924,7 +1848,6 @@ Here's an example in which the `AppComponent.fontSizePx` is two-way bound to the
下面的例子中,`AppComponent.fontSize` 被双向绑定到 `SizerComponent`
<code-example path="template-syntax/src/app/app.component.html" linenums="false" title="src/app/app.component.html (two-way-1)" region="two-way-1">
</code-example>
The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value.
@ -1943,7 +1866,6 @@ Angular _desugars_ the `SizerComponent` binding into this:
Angular 将 `SizerComponent` 的绑定分解成这样:
<code-example path="template-syntax/src/app/app.component.html" linenums="false" title="src/app/app.component.html (two-way-2)" region="two-way-2">
</code-example>
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
@ -1990,7 +1912,6 @@ Why create a directive to handle a click when you can write a simple binding suc
如果能用简单的绑定达到目的,为什么还要创建指令来处理点击事件呢?
<code-example path="template-syntax/src/app/app.component.html" region="event-binding-1" title="src/app/app.component.html" linenums="false">
</code-example>
You still benefit from directives that simplify complex tasks.
@ -2060,7 +1981,6 @@ A [class binding](guide/template-syntax#class-binding) is a good way to add or r
[CSS 类绑定](guide/template-syntax#class-binding) 是添加或删除*单个*类的最佳途径。
<code-example path="template-syntax/src/app/app.component.html" region="class-binding-3a" title="src/app/app.component.html" linenums="false">
</code-example>
To add or remove *many* CSS classes at the same time, the `NgClass` directive may be the better choice.
@ -2080,7 +2000,6 @@ Consider a `setCurrentClasses` component method that sets a component property,
组件方法 `setCurrentClasses` 可以把组件的属性 `currentClasses` 设置为一个对象,它将会根据三个其它组件的状态为 `true``false` 而添加或移除三个类。
<code-example path="template-syntax/src/app/app.component.ts" region="setClasses" title="src/app/app.component.ts" linenums="false">
</code-example>
Adding an `ngClass` property binding to `currentClasses` sets the element's classes accordingly:
@ -2088,7 +2007,6 @@ Adding an `ngClass` property binding to `currentClasses` sets the element's clas
`NgClass` 属性绑定到 `currentClasses`,根据它来设置此元素的 CSS 类:
<code-example path="template-syntax/src/app/app.component.html" region="NgClass-1" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2116,7 +2034,6 @@ A [style binding](guide/template-syntax#style-binding) is an easy way to set a *
[样式绑定](guide/template-syntax#style-binding)是设置*单一*样式值的简单方式。
<code-example path="template-syntax/src/app/app.component.html" region="NgStyle-1" title="src/app/app.component.html" linenums="false">
</code-example>
To set *many* inline styles at the same time, the `NgStyle` directive may be the better choice.
@ -2135,7 +2052,6 @@ with an object that defines three styles, based on the state of three other comp
来看看组件的 `setCurrentStyles` 方法,它会根据另外三个属性的状态把组件的 `currentStyles` 属性设置为一个定义了三个样式的对象:
<code-example path="template-syntax/src/app/app.component.ts" region="setStyles" title="src/app/app.component.ts" linenums="false">
</code-example>
Adding an `ngStyle` property binding to `currentStyles` sets the element's styles accordingly:
@ -2143,7 +2059,6 @@ Adding an `ngStyle` property binding to `currentStyles` sets the element's style
`NgStyle` 属性绑定到 `currentStyles`,以据此设置此元素的样式:
<code-example path="template-syntax/src/app/app.component.html" region="NgStyle-2" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2172,7 +2087,6 @@ Two-way data binding with the `NgModel` directive makes that easy. Here's an exa
使用 `NgModel` 指令进行双向数据绑定可以简化这种工作。例子如下:
<code-example path="template-syntax/src/app/app.component.html" linenums="false" title="src/app/app.component.html (NgModel-1)" region="NgModel-1">
</code-example>
#### _FormsModule_ is required to use _ngModel_
@ -2192,7 +2106,6 @@ Here's how to import the `FormsModule` to make `[(ngModel)]` available.
导入 `FormsModule` 并让 `[(ngModel)]` 可用的代码如下:
<code-example path="template-syntax/src/app/app.module.1.ts" linenums="false" title="src/app/app.module.ts (FormsModule import)">
</code-example>
#### Inside <span class="syntax">[(ngModel)]</span>
@ -2206,7 +2119,6 @@ the `<input>` element's `value` property and `input` event.
回头看看 `name` 绑定,注意,你可以通过分别绑定到 `<input>` 元素的 `value` 属性和 `input` 事件来达到同样的效果。
<code-example path="template-syntax/src/app/app.component.html" region="without-NgModel" title="src/app/app.component.html" linenums="false">
</code-example>
That's cumbersome. Who can remember which element property to set and which element event emits user changes?
@ -2221,7 +2133,6 @@ That `ngModel` directive hides these onerous details behind its own `ngModel` i
`ngModel` 指令通过自己的输入属性 `ngModel` 和输出属性 `ngModelChange` 隐藏了那些细节。
<code-example path="template-syntax/src/app/app.component.html" region="NgModel-3" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2270,7 +2181,6 @@ with a single declaration, which it can with the `[(ngModel)]` syntax:
你不用被迫两次引用这个数据属性Angular 可以捕获该元素的数据属性,并且通过一个简单的声明来设置它,这样它就可以使用 `[(ngModel)]` 语法了。
<code-example path="template-syntax/src/app/app.component.html" region="NgModel-1" title="src/app/app.component.html" linenums="false">
</code-example>
Is `[(ngModel)]` all you need? Is there ever a reason to fall back to its expanded form?
@ -2288,7 +2198,6 @@ The following contrived example forces the input value to uppercase:
下面这个生造的例子强制输入框的内容变成大写:
<code-example path="template-syntax/src/app/app.component.html" region="NgModel-4" title="src/app/app.component.html" linenums="false">
</code-example>
Here are all variations in action, including the uppercase version:
@ -2368,7 +2277,6 @@ Bind the directive to a condition expression like `isActive` in this example.
在下面的例子中,该指令绑定到了类似于 `isActive` 这样的条件表达式。
<code-example path="template-syntax/src/app/app.component.html" region="NgIf-1" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="alert is-critical">
@ -2395,7 +2303,6 @@ You can control the visibility of an element with a
你也可以通过[类绑定](guide/template-syntax#class-binding)或[样式绑定](guide/template-syntax#style-binding)来显示或隐藏一个元素。
<code-example path="template-syntax/src/app/app.component.html" region="NgIf-3" title="src/app/app.component.html" linenums="false">
</code-example>
Hiding an element is quite different from removing an element with `NgIf`.
@ -2445,7 +2352,6 @@ The `nullHero` will never be displayed.
`nullHero` 永远不会显示。
<code-example path="template-syntax/src/app/app.component.html" region="NgIf-2" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2477,7 +2383,6 @@ Here is an example of `NgForOf` applied to a simple `<div>`:
下例中,`NgFor` 应用在一个简单的 `<div>` 上:
<code-example path="template-syntax/src/app/app.component.html" region="NgFor-1" title="src/app/app.component.html" linenums="false">
</code-example>
You can also apply an `NgForOf` to a component element, as in this example:
@ -2485,7 +2390,6 @@ You can also apply an `NgForOf` to a component element, as in this example:
也可以把 `NgFor` 应用在一个组件元素上,就下例这样:
<code-example path="template-syntax/src/app/app.component.html" region="NgFor-2" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="alert is-critical">
@ -2552,7 +2456,6 @@ and then passed in a binding to the `hero` property of the `<hero-detail>` compo
这里它首先在一个插值表达式中被引用到,然后通过一个绑定把它传给了 `<hero-detail>` 组件的 `hero` 属性。
<code-example path="template-syntax/src/app/app.component.html" region="NgFor-1-2" title="src/app/app.component.html" linenums="false">
</code-example>
Learn more about _template input variables_ in the
@ -2575,7 +2478,6 @@ The next example captures the `index` in a variable named `i` and displays it wi
下面这个例子把 `index` 捕获到了 `i` 变量中,并且把它显示在英雄名字的前面。
<code-example path="template-syntax/src/app/app.component.html" region="NgFor-3" title="src/app/app.component.html" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2621,7 +2523,6 @@ In this case, that value is the hero's `id`.
在这里,这个值就是英雄的 `id`
<code-example path="template-syntax/src/app/app.component.ts" region="trackByHeroes" title="src/app/app.component.ts" linenums="false">
</code-example>
In the microsyntax expression, set `trackBy` to this method.
@ -2629,7 +2530,6 @@ In the microsyntax expression, set `trackBy` to this method.
在微语法中,把 `trackBy` 设置为该方法。
<code-example path="template-syntax/src/app/app.component.html" region="trackBy" title="src/app/app.component.html" linenums="false">
</code-example>
Here is an illustration of the _trackBy_ effect.
@ -2674,7 +2574,6 @@ Angular 只会把*选中的*元素放进 DOM 中。
`NgSwitch` 实际上包括三个相互协作的指令:`NgSwitch`、`NgSwitchCase` 和 `NgSwitchDefault`,例子如下:
<code-example path="template-syntax/src/app/app.component.html" region="NgSwitch" title="src/app/app.component.html" linenums="false">
</code-example>
<figure>
@ -2726,7 +2625,6 @@ For example, you could replace the `<confused-hero>` switch case with the follow
比如,你可以把 `<confused-hero>` 分支改成这样:
<code-example path="template-syntax/src/app/app.component.html" region="NgSwitch-div" title="src/app/app.component.html" linenums="false">
</code-example>
<hr/>
@ -2754,7 +2652,6 @@ The `#phone` declares a `phone` variable on an `<input>` element.
`#phone` 的意思就是声明一个名叫 `phone` 的变量来引用 `<input>` 元素。
<code-example path="template-syntax/src/app/app.component.html" region="ref-var" title="src/app/app.component.html" linenums="false">
</code-example>
You can refer to a template reference variable _anywhere_ in the template.
@ -2765,7 +2662,6 @@ consumed in a `<button>` on the other side of the template
比如声明在 `<input>` 上的 `phone` 变量就是在模板另一侧的 `<button>` 上使用的。
<code-example path="template-syntax/src/app/app.component.html" region="ref-phone" title="src/app/app.component.html" linenums="false">
</code-example>
<h3 class="no-toc">How a reference variable gets its value</h3>
@ -2789,7 +2685,6 @@ The following is a *simplified* version of the form example in the [Forms](guide
下面是[表单](guide/forms)一章中表单范例的*简化版*。
<code-example path="template-syntax/src/app/hero-form.component.html" title="src/app/hero-form.component.html" linenums="false">
</code-example>
A template reference variable, `heroForm`, appears three times in this example, separated
@ -2841,7 +2736,6 @@ This example declares the `fax` variable as `ref-fax` instead of `#fax`.
下面的例子中就用把 `fax` 变量声明成了 `ref-fax` 而不是 `#fax`
<code-example path="template-syntax/src/app/app.component.html" region="ref-fax" title="src/app/app.component.html" linenums="false">
</code-example>
<hr/>
@ -2892,7 +2786,6 @@ In such binding expressions, the component's property or method is to the _right
在下面的例子中,`iconUrl` 和 `onSave` 是组件的成员,它们在 `=` 右侧引号语法中被引用了。
<code-example path="template-syntax/src/app/app.component.html" region="io-1" title="src/app/app.component.html" linenums="false">
</code-example>
The `iconUrl` and `onSave` are members of the `AppComponent` class.
@ -2930,7 +2823,6 @@ In the following example, the `AppComponent` template binds `AppComponent` class
下面的例子中,`AppComponent` 的模板把 `AppComponent` 类的成员绑定到了 `HeroDetailComponent`(选择器为 `'app-hero-detail'` 的属性上。
<code-example path="template-syntax/src/app/app.component.html" region="io-2" title="src/app/app.component.html" linenums="false">
</code-example>
The Angular compiler _may_ reject these bindings with errors like this one:
@ -2938,10 +2830,8 @@ The Angular compiler _may_ reject these bindings with errors like this one:
Angular 的编译器*可能*会对这些绑定报错,就像这样:
<code-example language="sh" class="code-shell">
Uncaught Error: Template parse errors:
Can't bind to 'hero' since it isn't a known property of 'app-hero-detail'
</code-example>
You know that `HeroDetailComponent` has `hero` and `deleteRequest` properties.
@ -3013,7 +2903,6 @@ because the data bound properties are annotated with `@Input()` and `@Output()`
在本章的例子中,绑定到 `HeroDetailComponent` 不会失败,这是因为这些要进行数据绑定的属性都带有 `@Input()``@Output()` 装饰器。
<code-example path="template-syntax/src/app/hero-detail.component.ts" region="input-output-1" title="src/app/hero-detail.component.ts" linenums="false">
</code-example>
<div class="l-sub-section">
@ -3024,7 +2913,6 @@ of the directive metadata, as in this example:
另外,还可以在指令元数据的 `inputs``outputs` 数组中标记出这些成员。比如这个例子:
<code-example path="template-syntax/src/app/hero-detail.component.ts" region="input-output-2" title="src/app/hero-detail.component.ts" linenums="false">
</code-example>
</div>
@ -3077,7 +2965,6 @@ you expect to bind to an event property that is also called `myClick`.
希望绑定的事件属性也叫 `myClick`
<code-example path="template-syntax/src/app/app.component.html" region="myClick" title="src/app/app.component.html" linenums="false">
</code-example>
However, the directive name is often a poor choice for the name of a property within the directive class.
@ -3101,7 +2988,6 @@ You can specify the alias for the property name by passing it into the input/out
把别名传进@Input/@Output 装饰器,就可以为属性指定别名,就像这样:
<code-example path="template-syntax/src/app/click.directive.ts" region="output-myClick" title="src/app/click.directive.ts" linenums="false">
</code-example>
<div class="l-sub-section">
@ -3114,7 +3000,6 @@ the directive property name on the *left* and the public alias on the *right*:
可以写一个冒号 (`:`) 分隔的字符串,*左侧*是指令中的属性名,*右侧*则是公共别名。
<code-example path="template-syntax/src/app/click.directive.ts" region="output-myClick2" title="src/app/click.directive.ts" linenums="false">
</code-example>
</div>
@ -3153,7 +3038,6 @@ Angular [管道](guide/pipes)对像这样的小型转换来说是个明智的选
它们很容易用于模板表达式中,只要使用**管道操作符 (`|`) **就行了。
<code-example path="template-syntax/src/app/app.component.html" region="pipes-1" title="src/app/app.component.html" linenums="false">
</code-example>
The pipe operator passes the result of an expression on the left to a pipe function on the right.
@ -3165,7 +3049,6 @@ You can chain expressions through multiple pipes:
还可以通过多个管道串联表达式:
<code-example path="template-syntax/src/app/app.component.html" region="pipes-2" title="src/app/app.component.html" linenums="false">
</code-example>
And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe:
@ -3173,7 +3056,6 @@ And you can also [apply parameters](guide/pipes#parameterizing-a-pipe) to a pipe
还能对它们使用参数:
<code-example path="template-syntax/src/app/app.component.html" region="pipes-3" title="src/app/app.component.html" linenums="false">
</code-example>
The `json` pipe is particularly helpful for debugging bindings:
@ -3181,7 +3063,6 @@ The `json` pipe is particularly helpful for debugging bindings:
`json` 管道对调试绑定特别有用:
<code-example path="template-syntax/src/app/app.component.html" linenums="false" title="src/app/app.component.html (pipes-json)" region="pipes-json">
</code-example>
The generated output would look something like this
@ -3189,12 +3070,10 @@ The generated output would look something like this
它生成的输出是这样的:
<code-example language="json">
{ "id": 0, "name": "Hercules", "emotion": "happy",
"birthdate": "1970-02-25T08:00:00.000Z",
"url": "http://www.imdb.com/title/tt0065832/",
"rate": 325 }
</code-example>
<hr/>
@ -3213,7 +3092,6 @@ Angular 的**安全导航操作符 (`?.`) **是一种流畅而便利的方式,
下例中,当 `currentHero` 为空时,保护视图渲染器,让它免于失败。
<code-example path="template-syntax/src/app/app.component.html" region="safe-2" title="src/app/app.component.html" linenums="false">
</code-example>
What happens when the following data bound `title` property is null?
@ -3221,7 +3099,6 @@ What happens when the following data bound `title` property is null?
如果下列数据绑定中 `title` 属性为空,会发生什么?
<code-example path="template-syntax/src/app/app.component.html" region="safe-1" title="src/app/app.component.html" linenums="false">
</code-example>
The view still renders but the displayed value is blank; you see only "The title is" with nothing after it.
@ -3236,9 +3113,7 @@ that displays the `name` of a null hero.
假设模板表达式涉及属性路径,在下例中,显示一个空 (null) 英雄的 `firstName`
<code-example language="html">
The null hero's name is {{nullHero.name}}
</code-example>
JavaScript throws a null reference error, and so does Angular:
@ -3246,9 +3121,7 @@ JavaScript throws a null reference error, and so does Angular:
JavaScript 抛出了空引用错误Angular 也是如此:
<code-example format="nocode">
TypeError: Cannot read property 'name' of null in [null].
</code-example>
Worse, the *entire view disappears*.
@ -3283,7 +3156,6 @@ You could code around that problem with [*ngIf](guide/template-syntax#ngIf).
可以通过用[NgIf](guide/template-syntax#ngIf)代码环绕它来解决这个问题。
<code-example path="template-syntax/src/app/app.component.html" region="safe-4" title="src/app/app.component.html" linenums="false">
</code-example>
You could try to chain parts of the property path with `&&`, knowing that the expression bails out
@ -3292,7 +3164,6 @@ when it encounters the first null.
或者可以尝试通过 `&&` 来把属性路径的各部分串起来,让它在遇到第一个空值的时候,就返回空。
<code-example path="template-syntax/src/app/app.component.html" region="safe-5" title="src/app/app.component.html" linenums="false">
</code-example>
These approaches have merit but can be cumbersome, especially if the property path is long.
@ -3310,7 +3181,6 @@ Angular 安全导航操作符 (`?.`) 是在属性路径中保护空值的更加
显示是空的,但应用正常工作,而没有发生错误。
<code-example path="template-syntax/src/app/app.component.html" region="safe-6" title="src/app/app.component.html" linenums="false">
</code-example>
It works perfectly with long property paths such as `a?.b?.c?.d`.
@ -3352,7 +3222,6 @@ For example, after you use [*ngIf](guide/template-syntax#ngIf) to check that `he
例如,在用[*ngIf](guide/template-syntax#ngIf)来检查过 `hero` 是已定义的之后,就可以断言 `hero` 属性一定是已定义的。
<code-example path="template-syntax/src/app/app.component.html" region="non-null-assertion-1" title="src/app/app.component.html" linenums="false">
</code-example>
When the Angular compiler turns your template into TypeScript code,
@ -3390,7 +3259,6 @@ the expression to [the `any` type](http://www.typescriptlang.org/docs/handbook/b
有时候,绑定表达式可能会报类型错误,并且它不能或很难指定类型。要消除这种报错,你可以使用 `$any` 转换函数来把表达式转换成 [`any` 类型](http://www.typescriptlang.org/docs/handbook/basic-types.html#any)。
<code-example path="template-syntax/src/app/app.component.html" region="any-type-cast-function-1" title="src/app/app.component.html" linenums="false">
</code-example>
In this example, when the Angular compiler turns your template into TypeScript code,
@ -3405,7 +3273,6 @@ the component.
`$any` 转换函数可以和 `this` 联合使用,以便访问组件中未声明过的成员。
<code-example path="template-syntax/src/app/app.component.html" region="any-type-cast-function-2" title="src/app/app.component.html" linenums="false">
</code-example>
The `$any` cast function can be used anywhere in a binding expression where a method call is valid.
@ -3419,5 +3286,4 @@ The `$any` cast function can be used anywhere in a binding expression where a me
You've completed this survey of template syntax.
Now it's time to put that knowledge to work on your own components and directives.
你完成了模板语法的概述。现在,该把如何写组件和指令的知识投入到实际工作当中了。

View File

@ -39,9 +39,7 @@ Just run this one CLI command:
运行下列 CLI 命令即可:
<code-example language="sh" class="code-shell">
ng test
</code-example>
The `ng test` command builds the app in _watch mode_,
@ -54,14 +52,12 @@ The console output looks a bit like this:
它的控制台输出一般是这样的:
<code-example language="sh" class="code-shell">
10% building modules 1/1 modules 0 active
...INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/
...INFO [launcher]: Launching browser Chrome ...
...INFO [launcher]: Starting browser Chrome
...INFO [Chrome ...]: Connected on socket ...
Chrome ...: Executed 3 of 3 SUCCESS (0.135 secs / 0.205 secs)
</code-example>
The last line of the log is the most important.
@ -286,7 +282,6 @@ array of the services that you'll test or mock.
path="testing/src/app/demo/demo.testbed.spec.ts"
region="value-service-before-each"
title="app/demo/demo.testbed.spec.ts (provide ValueService in beforeEach">
</code-example>
Then inject it inside a test by calling `TestBed.get()` with the service class as the argument.
@ -296,7 +291,6 @@ Then inject it inside a test by calling `TestBed.get()` with the service class a
<code-example
path="testing/src/app/demo/demo.testbed.spec.ts"
region="value-service-inject-it">
</code-example>
Or inside the `beforeEach()` if you prefer to inject the service as part of your setup.
@ -306,7 +300,6 @@ Or inside the `beforeEach()` if you prefer to inject the service as part of your
<code-example
path="testing/src/app/demo/demo.testbed.spec.ts"
region="value-service-inject-before-each">
</code-example>
When testing a service with a dependency, provide the mock in the `providers` array.
@ -320,7 +313,6 @@ In the following example, the mock is a spy object.
<code-example
path="testing/src/app/demo/demo.testbed.spec.ts"
region="master-service-before-each" linenums="false">
</code-example>
The test consumes that spy in the same way it did earlier.
@ -330,7 +322,6 @@ The test consumes that spy in the same way it did earlier.
<code-example
path="testing/src/app/demo/demo.testbed.spec.ts"
region="master-service-it">
</code-example>
{@a no-before-each}
@ -361,7 +352,6 @@ Begin by putting re-usable, preparatory code in a _setup_ function instead of `b
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-setup"
title="app/demo/demo.spec.ts (setup)" linenums="false">
</code-example>
The `setup()` function returns an object literal
@ -380,7 +370,6 @@ with steps that manipulate the test subject and assert expectations.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-test" linenums="false">
</code-example>
Notice how the test uses
@ -393,7 +382,6 @@ to extract the setup variables that it needs.
<code-example
path="testing/src/app/demo/demo.spec.ts"
region="no-before-each-setup-call">
</code-example>
Many developers feel this approach is cleaner and more explicit than the
@ -427,7 +415,6 @@ test any service with a dependency.
path="testing/src/app/model/hero.service.spec.ts"
region="test-with-spies"
title="app/model/hero.service.spec.ts (tests with spies)">
</code-example>
<div class="alert is-important">
@ -521,7 +508,6 @@ Consider this `LightswitchComponent` which toggles a light on and off
path="testing/src/app/demo/demo.ts"
region="LightswitchComp"
title="app/demo/demo.ts (LightswitchComp)" linenums="false">
</code-example>
You might decide only to test that the `clicked()` method
@ -542,7 +528,6 @@ Do the same with the component class.
path="testing/src/app/demo/demo.spec.ts"
region="Lightswitch"
title="app/demo/demo.spec.ts (Lightswitch tests)" linenums="false">
</code-example>
Here is the `DashboardHeroComponent` from the _Tour of Heroes_ tutorial.
@ -553,7 +538,6 @@ Here is the `DashboardHeroComponent` from the _Tour of Heroes_ tutorial.
path="testing/src/app/dashboard/dashboard-hero.component.ts"
region="class"
title="app/dashboard/dashboard-hero.component.ts (component)" linenums="false">
</code-example>
It appears within the template of a parent component,
@ -571,7 +555,6 @@ or its parent component.
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="class-only"
title="app/dashboard/dashboard-hero.component.spec.ts (class tests)" linenums="false">
</code-example>
When a component has dependencies, you may wish to use the `TestBed` to both
@ -587,7 +570,6 @@ The following `WelcomeComponent` depends on the `UserService` to know the name o
path="testing/src/app/welcome/welcome.component.ts"
region="class"
title="app/welcome/welcome.component.ts" linenums="false">
</code-example>
You might start by creating a mock of the `UserService` that meets the minimum needs of this component.
@ -598,7 +580,6 @@ You might start by creating a mock of the `UserService` that meets the minimum n
path="testing/src/app/welcome/welcome.component.spec.ts"
region="mock-user-service"
title="app/welcome/welcome.component.spec.ts (MockUserService)" linenums="false">
</code-example>
Then provide and inject _both the_ **component** _and the service_ in the `TestBed` configuration.
@ -609,7 +590,6 @@ Then provide and inject _both the_ **component** _and the service_ in the `TestB
path="testing/src/app/welcome/welcome.component.spec.ts"
region="class-only-before-each"
title="app/welcome/welcome.component.spec.ts (class-only setup)" linenums="false">
</code-example>
Then exercise the component class, remembering to call the [lifecycle hook methods](guide/lifecycle-hooks) as Angular does when running the app.
@ -620,7 +600,6 @@ Then exercise the component class, remembering to call the [lifecycle hook metho
path="testing/src/app/welcome/welcome.component.spec.ts"
region="class-only-tests"
title="app/welcome/welcome.component.spec.ts (class-only tests)" linenums="false">
</code-example>
### Component DOM testing
@ -702,9 +681,7 @@ For example, the following CLI command generates a `BannerComponent` in the `app
比如,下列 CLI 命令会在 `app/banner` 文件夹中创建带有内联模板和内联样式的 `BannerComponent`
<code-example language="sh" class="code-shell">
ng generate component banner --inline-template --inline-style --module app
</code-example>
It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this:
@ -715,7 +692,6 @@ It also generates an initial test file for the component, `banner-external.compo
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v1"
title="app/banner/banner-external.component.spec.ts (initial)" linenums="false">
</code-example>
#### Reduce the setup
@ -741,7 +717,6 @@ For now, you can radically reduce this test file to a more manageable size:
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v2"
title="app/banner/banner-initial.component.spec.ts (minimal)" linenums="false">
</code-example>
In this example, the metadata object passed to `TestBed.configureTestingModule`
@ -752,7 +727,6 @@ simply declares `BannerComponent`, the component to test.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="configureTestingModule">
</code-example>
<div class="l-sub-section">
@ -784,7 +758,6 @@ After configuring `TestBed`, you call its `createComponent()` method.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="createComponent">
</code-example>
`TestBed.createComponent()` creates an instance of the `BannerComponent`,
@ -829,7 +802,6 @@ Access the component instance through the fixture and confirm it exists with a J
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="componentInstance">
</code-example>
#### _beforeEach()_
@ -845,7 +817,6 @@ you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v3"
linenums="false">
</code-example>
Now add a test that gets the component's element from `fixture.nativeElement` and
@ -856,7 +827,6 @@ looks for the expected text.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-2">
</code-example>
{@a native-element}
@ -896,7 +866,6 @@ Here's another test that calls `HTMLElement.querySelector` to get the paragraph
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-3">
</code-example>
{@a debug-element}
@ -910,7 +879,6 @@ Angular 的*夹具*可以通过 `fixture.nativeElement` 直接提供组件的元
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="nativeElement">
</code-example>
This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`.
@ -920,7 +888,6 @@ This is actually a convenience method, implemented as `fixture.debugElement.nati
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="debugElement-nativeElement">
</code-example>
There's a good reason for this circuitous path to the element.
@ -956,7 +923,6 @@ Here's the previous test, re-implemented with `fixture.debugElement.nativeElemen
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-4">
</code-example>
The `DebugElement` has other methods and properties that
@ -971,7 +937,6 @@ You import the `DebugElement` symbol from the Angular core library.
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="import-debug-element">
</code-example>
{@a by-css}
@ -1003,7 +968,6 @@ library for the runtime platform. Here's the `By` import for the browser platfor
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="import-by">
</code-example>
The following example re-implements the previous test with
@ -1014,7 +978,6 @@ The following example re-implements the previous test with
<code-example
path="testing/src/app/banner/banner-initial.component.spec.ts"
region="v4-test-5">
</code-example>
Some noteworthy observations:
@ -1073,7 +1036,6 @@ the component's `title` property like this.
path="testing/src/app/banner/banner.component.ts"
region="component"
title="app/banner/banner.component.ts" linenums="false">
</code-example>
Simple as this is, you decide to add a test to confirm that component
@ -1099,7 +1061,6 @@ and assign it to the `h1` variable.
path="testing/src/app/banner/banner.component.spec.ts"
region="setup"
title="app/banner/banner.component.spec.ts (setup)" linenums="false">
</code-example>
{@a detect-changes}
@ -1117,7 +1078,6 @@ Your instinct is to write a test that immediately inspects the `<h1>` like this:
<code-example
path="testing/src/app/banner/banner.component.spec.ts"
region="expect-h1-default-v1">
</code-example>
_That test fails_ with the message:
@ -1148,7 +1108,6 @@ a fact confirmed in the revised test:
<code-example
path="testing/src/app/banner/banner.component.spec.ts" region="test-w-o-detect-changes" linenums="false">
</code-example>
#### _detectChanges()_
@ -1162,7 +1121,6 @@ Only then does the `<h1>` have the expected title.
<code-example
path="testing/src/app/banner/banner.component.spec.ts"
region="expect-h1-default">
</code-example>
Delayed change detection is intentional and useful.
@ -1179,7 +1137,6 @@ Here's another test that changes the component's `title` property _before_ calli
<code-example
path="testing/src/app/banner/banner.component.spec.ts"
region="after-change">
</code-example>
{@a auto-detect-changes}
@ -1293,7 +1250,6 @@ as the following variant of `BannerComponent` does.
path="testing/src/app/banner/banner-external.component.ts"
region="metadata"
title="app/banner/banner-external.component.ts (metadata)" linenums="false">
</code-example>
This syntax tells the Angular compiler to read the external files during component compilation.
@ -1313,11 +1269,9 @@ For example, if you run the `BannerComponent` tests in a web coding environment
比如,如果你在像 [plunker](http://plnkr.co/) 这样的 Web 编程环境下运行 `BannerComponent` 的测试,就会看到如下信息:
<code-example language="sh" class="code-shell" hideCopy>
Error: This test module uses the component BannerComponent
which is using a "templateUrl" or "styleUrls", but they were never compiled.
Please call "TestBed.compileComponents" before your test.
</code-example>
You get this test failure message when the runtime environment
@ -1392,7 +1346,6 @@ and its tests:
path="testing/src/app/welcome/welcome.component.spec.ts"
region="user-service-stub"
title="app/welcome/welcome.component.spec.ts" linenums="false">
</code-example>
{@a get-injected-service}
@ -1423,7 +1376,6 @@ The component injector is a property of the fixture's `DebugElement`.
path="testing/src/app/welcome/welcome.component.spec.ts"
region="injected-service"
title="WelcomeComponent's injector">
</code-example>
{@a testbed-get}
@ -1447,7 +1399,6 @@ so it is safe to call `TestBed.get()` as follows:
path="testing/src/app/welcome/welcome.component.spec.ts"
region="inject-from-testbed"
title="TestBed injector">
</code-example>
<div class="l-sub-section">
@ -1537,7 +1488,6 @@ The `TwainComponent` displays Mark Twain quotes.
path="testing/src/app/twain/twain.component.ts"
region="template"
title="app/twain/twain.component.ts (template)" linenums="false">
</code-example>
Note that value of the component's `quote` property passes through an `AsyncPipe`.
@ -1555,7 +1505,6 @@ the `quote` property returns an `Observable`.
path="testing/src/app/twain/twain.component.ts"
region="get-quote"
title="app/twain/twain.component.ts (getQuote)" linenums="false">
</code-example>
The `TwainComponent` gets quotes from an injected `TwainService`.
@ -1593,7 +1542,6 @@ They should emulate such calls. The setup in this `app/twain/twain.component.spe
path="testing/src/app/twain/twain.component.spec.ts"
region="setup"
title="app/twain/twain.component.spec.ts (setup)" linenums="false">
</code-example>
{@a service-spy}
@ -1605,7 +1553,6 @@ Focus on the spy.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="spy">
</code-example>
The spy is designed such that any call to `getQuote` receives an Observable with a test quote.
@ -1633,7 +1580,6 @@ you can often turn asynchronous processes into synchronous tests.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="sync-test">
</code-example>
Because the spy result returns synchronously, the `getQuote()` method updates
@ -1665,7 +1611,6 @@ The following test confirms the expected behavior when the service returns an `E
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="error-test">
</code-example>
Note that the `it()` function receives an argument of the following form.
@ -1733,7 +1678,6 @@ from the `getQuote()` spy like this.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="async-setup">
</code-example>
#### Async observable helpers
@ -1751,7 +1695,6 @@ Or you can copy this one from the sample code.
path="testing/src/testing/async-observable-helpers.ts"
region="async-data"
title="testing/async-observable-helpers.ts">
</code-example>
This helper's observable emits the `data` value in the next turn of the JavaScript engine.
@ -1781,7 +1724,6 @@ There's a similar helper for producing an async error.
<code-example
path="testing/src/testing/async-observable-helpers.ts"
region="async-error">
</code-example>
#### More async tests
@ -1801,7 +1743,6 @@ in the real world.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="fake-async-test">
</code-example>
Notice that the quote element displays the placeholder value (`'...'`) after `ngOnInit()`.
@ -1855,7 +1796,6 @@ Here's the previous `fakeAsync()` test, re-written with the `async()` utility.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="async-test">
</code-example>
The `async()` utility hides some asynchronous boilerplate by arranging for the tester's code
@ -1928,7 +1868,6 @@ The first one subscribes to the `Observable` exposed to the template by the comp
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="quote-done-test" linenums="false">
</code-example>
The RxJS `last()` operator emits the observable's last value before completing, which will be the test quote.
@ -1951,7 +1890,6 @@ can give you that information and make assertions about the state of the view.
<code-example
path="testing/src/app/twain/twain.component.spec.ts"
region="spy-done-test" linenums="false">
</code-example>
<hr>
@ -2003,7 +1941,6 @@ Then import the symbols you need.
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="import-marbles"
title="app/twain/twain.component.marbles.spec.ts (import marbles)" linenums="false">
</code-example>
Here's the complete test for getting a quote:
@ -2013,7 +1950,6 @@ Here's the complete test for getting a quote:
<code-example
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="get-quote-test" linenums="false">
</code-example>
Notice that the Jasmine test is synchronous. There's no `fakeAsync()`.
@ -2036,7 +1972,6 @@ In the second argument you map the value marker (`x`) to the emitted value (`tes
<code-example
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="test-quote-marbles" linenums="false">
</code-example>
The marble library constructs the corresponding observable, which the
@ -2052,7 +1987,6 @@ you tell the `TestScheduler` to _flush_ its queue of prepared tasks like this.
<code-example
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="test-scheduler-flush" linenums="false">
</code-example>
This step serves a purpose analogous to `tick()` and `whenStable()` in the
@ -2073,7 +2007,6 @@ Here's the marble testing version of the `getQuote()` error test.
<code-example
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="error-test" linenums="false">
</code-example>
It's still an async test, calling `fakeAsync()` and `tick()`, because the component itself
@ -2088,7 +2021,6 @@ Look at the marble observable definition.
<code-example
path="testing/src/app/twain/twain.component.marbles.spec.ts"
region="error-marbles" linenums="false">
</code-example>
This is a _cold_ observable that waits three frames and then emits an error,
@ -2172,7 +2104,6 @@ The `DashboardHeroComponent` is embedded in the `DashboardComponent` template li
path="testing/src/app/dashboard/dashboard.component.html"
region="dashboard-hero"
title="app/dashboard/dashboard.component.html (excerpt)" linenums="false">
</code-example>
The `DashboardHeroComponent` appears in an `*ngFor` repeater, which sets each component's `hero` input property
@ -2190,7 +2121,6 @@ Here's the component's full definition:
path="testing/src/app/dashboard/dashboard-hero.component.ts"
region="component"
title="app/dashboard/dashboard-hero.component.ts (component)" linenums="false">
</code-example>
While testing a component this simple has little intrinsic value, it's worth knowing how.
@ -2219,7 +2149,6 @@ A quick look at the `DashboardComponent` constructor discourages the first appro
path="testing/src/app/dashboard/dashboard.component.ts"
region="ctor"
title="app/dashboard/dashboard.component.ts (constructor)" linenums="false">
</code-example>
The `DashboardComponent` depends on the Angular router and the `HeroService`.
@ -2258,7 +2187,6 @@ Here's the meat of the spec file setup.
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="setup"
title="app/dashboard/dashboard-hero.component.spec.ts (setup)" linenums="false">
</code-example>
Note how the setup code assigns a test hero (`expectedHero`) to the component's `hero` property,
@ -2274,7 +2202,6 @@ The following test verifies that the hero name is propagated to the template via
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="name-test">
</code-example>
Because the [template](#dashboard-hero-component) passes the hero name through the Angular `UpperCasePipe`,
@ -2306,7 +2233,6 @@ the host component (`DashboardComponent` presumably) can hear:
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="click-test">
</code-example>
The component's `selected` property returns an `EventEmitter`,
@ -2353,7 +2279,6 @@ The test triggered a "click" event with a `null` event object.
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts" region="trigger-event-handler">
</code-example>
The test assumes (correctly in this case) that the runtime
@ -2386,7 +2311,6 @@ which is perfectly fine for _this component_.
<code-example
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="click-test-2">
</code-example>
{@a click-helper}
@ -2408,7 +2332,6 @@ in a helper such as the `click()` function below:
path="testing/src/testing/index.ts"
region="click-event"
title="testing/index.ts (click helper)" linenums="false">
</code-example>
The first parameter is the _element-to-click_. If you wish, you can pass a
@ -2441,7 +2364,6 @@ Here's the previous test, rewritten using the click helper.
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="click-test-3"
title="app/dashboard/dashboard-hero.component.spec.ts (test with click helper)">
</code-example>
<hr>
@ -2479,7 +2401,6 @@ that can be made satisfactorily with a _test host_ like this one:
region="test-host"
title="app/dashboard/dashboard-hero.component.spec.ts (test host)"
linenums="false">
</code-example>
This test host binds to `DashboardHeroComponent` as the `DashboardComponent` would
@ -2542,7 +2463,6 @@ The tests themselves are almost identical to the stand-alone version:
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="test-host-tests"
title="app/dashboard/dashboard-hero.component.spec.ts (test-host)" linenums="false">
</code-example>
Only the selected event test differs. It confirms that the selected `DashboardHeroComponent` hero
@ -2576,7 +2496,6 @@ which it injects together with the `HeroService`.
path="testing/src/app/dashboard/dashboard.component.ts"
region="ctor"
title="app/dashboard/dashboard.component.ts (constructor)" linenums="false">
</code-example>
Mocking the `HeroService` with a spy is a [familiar story](#component-with-async-service).
@ -2593,7 +2512,6 @@ Fortunately, not in this case because the `DashboardComponent` isn't doing much
path="testing/src/app/dashboard/dashboard.component.ts"
region="goto-detail"
title="app/dashboard/dashboard.component.ts (goToDetail)">
</code-example>
This is often the case with _routing components_.
@ -2612,7 +2530,6 @@ as providing a `HeroService` spy.
path="testing/src/app/dashboard/dashboard.component.spec.ts"
region="router-spy"
title="app/dashboard/dashboard.component.spec.ts (spies)" linenums="false">
</code-example>
The following test clicks the displayed hero and confirms that
@ -2624,7 +2541,6 @@ The following test clicks the displayed hero and confirms that
path="testing/src/app/dashboard/dashboard.component.spec.ts"
region="navigate-test"
title="app/dashboard/dashboard.component.spec.ts (navigate test)" linenums="false">
</code-example>
{@a routed-component-w-param}
@ -2728,7 +2644,6 @@ The following `ActivatedRouteStub` class serves as a test double for `ActivatedR
path="testing/src/testing/activated-route-stub.ts"
region="activated-route-stub"
title="testing/activated-route-stub.ts (ActivatedRouteStub)" linenums="false">
</code-example>
Consider placing such helpers in a `testing` folder sibling to the `app` folder.
@ -2798,7 +2713,6 @@ New heroes have `id=0` and a blank `name`. This test confirms that the component
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="route-no-id"
title="app/hero/hero-detail.component.spec.ts (no id)" linenums="false">
</code-example>
<hr>
@ -2824,7 +2738,6 @@ The `AppComponent`, for example, displays a navigation bar with anchors and thei
<code-example
path="testing/src/app/app.component.html"
title="app/app.component.html" linenums="false">
</code-example>
While the `AppComponent` _class_ is empty,
@ -2885,7 +2798,6 @@ and directive that play little or no role in the tests.
path="testing/src/app/app.component.spec.ts"
region="component-stubs"
title="app/app.component.spec.ts (stub declaration)" linenums="false">
</code-example>
The stub selectors match the selectors for the corresponding real components.
@ -2902,7 +2814,6 @@ components, directives, and pipes that need to be real.
path="testing/src/app/app.component.spec.ts"
region="testbed-stubs"
title="app/app.component.spec.ts (TestBed stubs)" linenums="false">
</code-example>
The `AppComponent` is the test subject, so of course you declare the real version.
@ -2930,7 +2841,6 @@ In the second approach, add `NO_ERRORS_SCHEMA` to the `TestBed.schemas` metadata
path="testing/src/app/app.component.spec.ts"
region="no-errors-schema"
title="app/app.component.spec.ts (NO_ERRORS_SCHEMA)" linenums="false">
</code-example>
The `NO_ERRORS_SCHEMA` tells the Angular compiler to ignore unrecognized elements and attributes.
@ -2992,7 +2902,6 @@ as seen in this example.
path="testing/src/app/app.component.spec.ts"
region="mixed-setup"
title="app/app.component.spec.ts (mixed setup)" linenums="false">
</code-example>
The Angular compiler creates the `BannerComponentStub` for the `<app-banner>` element
@ -3026,7 +2935,6 @@ seen in the `AppComponent` template.
path="testing/src/testing/router-link-directive-stub.ts"
region="router-link"
title="testing/router-link-directive-stub.ts (RouterLinkDirectiveStub)" linenums="false">
</code-example>
The URL bound to the `[routerLink]` attribute flows in to the directive's `linkParams` property.
@ -3071,7 +2979,6 @@ A little more setup triggers the initial data binding and gets references to the
path="testing/src/app/app.component.spec.ts"
region="test-setup"
title="app/app.component.spec.ts (test setup)" linenums="false">
</code-example>
Three points of special interest:
@ -3099,7 +3006,6 @@ The `AppComponent` links to validate are as follows:
path="testing/src/app/app.component.html"
region="links"
title="app/app.component.html (navigation links)" linenums="false">
</code-example>
{@a app-component-tests}
@ -3194,7 +3100,6 @@ But there's plenty of template complexity even in this simple form.
<code-example
path="testing/src/app/hero/hero-detail.component.html" title="app/hero/hero-detail.component.html" linenums="false">
</code-example>
Tests that exercise the component need ...
@ -3238,7 +3143,6 @@ Here is such a `Page` class for the `hero-detail.component.spec.ts`
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="page"
title="app/hero/hero-detail.component.spec.ts (Page)" linenums="false">
</code-example>
Now the important hooks for component manipulation and inspection are neatly organized and accessible from an instance of `Page`.
@ -3253,7 +3157,6 @@ A `createComponent` method creates a `page` object and fills in the blanks once
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="create-component"
title="app/hero/hero-detail.component.spec.ts (createComponent)" linenums="false">
</code-example>
The [_HeroDetailComponent_ tests](#tests-w-test-double) in an earlier section demonstrate how `createComponent` and `page`
@ -3271,7 +3174,6 @@ Here are a few more `HeroDetailComponent` tests to reinforce the point.
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="selected-tests"
title="app/hero/hero-detail.component.spec.ts (selected tests)" linenums="false">
</code-example>
<hr>
@ -3296,11 +3198,9 @@ If you run tests in a **non-CLI environment**, the tests may fail with a message
如果你在**非 CLI 环境**中运行测试,这些测试可能会报错,错误信息如下:
<code-example language="sh" class="code-shell" hideCopy>
Error: This test module uses the component BannerComponent
which is using a "templateUrl" or "styleUrls", but they were never compiled.
Please call "TestBed.compileComponents" before your test.
</code-example>
The root of the problem is at least one of the components involved in the test
@ -3312,7 +3212,6 @@ the following version of the `BannerComponent` does.
<code-example
path="testing/src/app/banner/banner-external.component.ts"
title="app/banner/banner-external.component.ts (external template & css)" linenums="false">
</code-example>
The test fails when the `TestBed` tries to create the component.
@ -3324,7 +3223,6 @@ The test fails when the `TestBed` tries to create the component.
region="configure-and-create"
title="app/banner/banner.component.spec.ts (setup that fails)"
avoid linenums="false">
</code-example>
Recall that the app hasn't been compiled.
@ -3367,9 +3265,7 @@ you'll see this error message
如果你忘了把测试函数标为异步的(比如忘了像稍后的代码中那样使用 `async()`),就会看到下列错误。
<code-example language="sh" class="code-shell" hideCopy>
Error: ViewDestroyedError: Attempt to use a destroyed view
</code-example>
</div>
@ -3393,7 +3289,6 @@ To follow this pattern, import the `async()` helper with the other testing symbo
<code-example
path="testing/src/app/banner/banner-external.component.spec.ts"
region="import-async">
</code-example>
#### The async _beforeEach_
@ -3408,7 +3303,6 @@ Write the first async `beforeEach` like this.
path="testing/src/app/banner/banner-external.component.spec.ts"
region="async-before-each"
title="app/banner/banner-external.component.spec.ts (async beforeEach)" linenums="false">
</code-example>
The `async()` helper function takes a parameterless function with the body of the setup.
@ -3467,7 +3361,6 @@ which include creating the component and querying for elements to inspect.
path="testing/src/app/banner/banner-external.component.spec.ts"
region="sync-before-each"
title="app/banner/banner-external.component.spec.ts (synchronous beforeEach)" linenums="false">
</code-example>
You can count on the test runner to wait for the first asynchronous `beforeEach` to finish before calling the second.
@ -3493,7 +3386,6 @@ into a `then(...)` callback.
path="testing/src/app/banner/banner-external.component.spec.ts"
region="one-before-each"
title="app/banner/banner-external.component.spec.ts (one beforeEach)" linenums="false">
</code-example>
#### _compileComponents()_ is harmless
@ -3529,7 +3421,6 @@ Earlier component tests configured the testing module with a few `declarations`
path="testing/src/app/dashboard/dashboard-hero.component.spec.ts"
region="config-testbed"
title="app/dashboard/dashboard-hero.component.spec.ts (configure TestBed)">
</code-example>
The `DashboardComponent` is simple. It needs no help.
@ -3576,7 +3467,6 @@ One approach is to configure the testing module from the individual pieces as in
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="setup-forms-module"
title="app/hero/hero-detail.component.spec.ts (FormsModule setup)" linenums="false">
</code-example>
<div class="l-sub-section">
@ -3611,7 +3501,6 @@ The test configuration can use the `SharedModule` too as seen in this alternativ
path="testing/src/app/hero/hero-detail.component.spec.ts"
region="setup-shared-module"
title="app/hero/hero-detail.component.spec.ts (SharedModule setup)" linenums="false">
</code-example>
It's a bit tighter and smaller, with fewer import statements (not shown).
@ -3743,13 +3632,11 @@ The [overide metadata object](#metadata-override-object) is a generic defined as
它接受两个参数:要改写的组件类(`HeroDetailComponent`),以及用于改写的元数据对象:
<code-example format="." language="javascript">
type MetadataOverride<T> = {
add?: T;
remove?: T;
set?: T;
};
</code-example>
A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties.
@ -3763,13 +3650,11 @@ The type parameter, `T`, is the kind of metadata you'd pass to the `@Component`
这个类型参数,`T`,是你会传递给 `@Component` 装饰器的元数据的类型。
<code-example format="." language="javascript">
selector?: string;
template?: string;
templateUrl?: string;
providers?: any[];
...
</code-example>
{@a spy-stub}
@ -4057,7 +3942,6 @@ Here's a summary of the stand-alone functions, in order of likely utility:
下面是一些独立函数的总结,以使用频率排序:
<table>
<tr>
<th>
@ -4272,7 +4156,6 @@ Here's a summary of the stand-alone functions, in order of likely utility:
</td>
</tr>
</table>
<hr>
@ -4297,14 +4180,12 @@ is a subset of the `@NgModule` metadata properties.
传递给 `configureTestingModule` 的模块定义是 `@NgModule` 元数据属性的子集。
<code-example format="." language="javascript">
type TestModuleMetadata = {
providers?: any[];
declarations?: any[];
imports?: any[];
schemas?: Array&lt;SchemaMetadata | any[]&gt;;
};
</code-example>
{@a metadata-override-object}
@ -4316,13 +4197,11 @@ appropriate to the method, that is, the parameter of an `@NgModule`,
每一个重载方法接受一个 `MetadataOverride<T>`,这里 `T` 是适合这个方法的元数据类型,也就是 `@NgModule`、`@Component`、`@Directive` 或者 `@Pipe` 的参数。
<code-example format="." language="javascript">
type MetadataOverride<T> = {
add?: T;
remove?: T;
set?: T;
};
</code-example>
{@a testbed-methods}
@ -4347,7 +4226,6 @@ Here are the most important static methods, in order of likely utility.
这里列出了最重要的静态方法,以使用频率排序:
<table>
<tr>
<th>
@ -4614,7 +4492,6 @@ Here are the most important static methods, in order of likely utility.
</td>
</tr>
</table>
A few of the `TestBed` instance methods are not covered by static `TestBed` _class_ methods.
@ -4650,7 +4527,6 @@ Here are the most important properties for testers, in order of likely utility.
下面是对测试最重要的属性,以使用频率排序:
<table>
<tr>
<th>
@ -4754,7 +4630,6 @@ Here are the most important properties for testers, in order of likely utility.
</td>
</tr>
</table>
{@a component-fixture-methods}
@ -4774,7 +4649,6 @@ Here are the most useful methods for testers.
下面是对测试最有用的方法。
<table>
<tr>
<th>
@ -4939,7 +4813,6 @@ Here are the most useful methods for testers.
</td>
</tr>
</table>
{@a debug-element-details}
@ -4960,7 +4833,6 @@ Here are the most useful `DebugElement` members for testers, in approximate orde
下面是 `DebugElement` 最有用的成员,以使用频率排序。
<table>
<tr>
<th>
@ -5267,7 +5139,6 @@ Here are the most useful `DebugElement` members for testers, in approximate orde
</td>
</tr>
</table>
{@a query-predicate}

View File

@ -102,7 +102,6 @@ You can suppress them with the following additional flag:
你可以使用另一个标志来禁止它们。
<code-example format=".">
"suppressImplicitAnyIndexErrors":true
</code-example>
@ -166,7 +165,6 @@ list of declaration files to be included:
因为《快速上手》的目标为 `es5`,所以你可以重写声明文件列表来包含:
<code-example format=".">
"lib": ["es2015", "dom"]
</code-example>

View File

@ -261,7 +261,6 @@ When you're done, the folder structure will look like this:
当做完这些后,文件夹的结构是这样的:
<code-example format="." language="none" linenums="false">
src/
index.html <t><i>app web page</i></t><t>应用的宿主页</t>
main.ts <t><i>bootstrapper for client app</i></t><t>客户端应用的引导程序</t>
@ -276,7 +275,6 @@ server.ts <t><i>* express web server</i></t><t>* Express 的
tsconfig.json <t><i>TypeScript client configuration</i></t><t>TypeScript 的客户端配置</t>
package.json <t><i>npm configuration</i></t><t>npm 配置</t>
webpack.server.config.js <t><i>* Webpack server configuration</i></t><t>* Webpack 的服务端配置</t>
</code-example>
The files marked with `*` are new and not in the original tutorial sample.
@ -326,9 +324,7 @@ Install them with the following commands:
使用下列命令安装它们:
<code-example format="." language="bash">
npm install --save @angular/platform-server @nguniversal/module-map-ngfactory-loader ts-loader @nguniversal/express-engine
</code-example>
{@a transition}
@ -364,7 +360,6 @@ Replace that import with this one:
把该导入改成这样:
<code-example path="universal/src/app/app.module.ts" region="browsermodule" title="src/app/app.module.ts (withServerTransition)">
</code-example>
Angular adds the `appId` value (which can be _any_ string) to the style-names of the server-rendered pages,
@ -377,7 +372,6 @@ You can get runtime information about the current platform and the `appId` by in
你可以通过依赖注入取得关于当前平台和 `appId` 的运行时信息。
<code-example path="universal/src/app/app.module.ts" region="platform-detection" title="src/app/app.module.ts (platform detection)">
</code-example>
{@a http-urls}
@ -413,7 +407,6 @@ Start by changing the `HeroService` constructor to take a second `origin` parame
先为 `HeroService` 的构造函数添加第二个 `origin` 参数,它是可选的,并通过 `APP_BASE_HREF` 令牌进行注入。
<code-example path="universal/src/app/hero.service.ts" region="ctor" title="src/app/hero.service.ts (constructor with optional origin)">
</code-example>
Note how the constructor prepends the origin (if it exists) to the `heroesUrl`.
@ -460,7 +453,6 @@ Create an `app.server.module.ts` file in the `src/app/` directory with the follo
`src/app/` 目录下创建 `app.server.module.ts` 文件,代码如下:
<code-example path="universal/src/app/app.server.module.ts" title="src/app/app.server.module.ts">
</code-example>
Notice that it imports first the client app's `AppModule`, the Angular Universal's `ServerModule` and the `ModuleMapLoaderModule`.
@ -512,7 +504,6 @@ Create a `server.ts` file in the root directory and add the following code:
在根目录下创建 `server.ts` 文件,并添加下列代码:
<code-example path="universal/server.ts" title="server.ts">
</code-example>
<div class="alert is-critical">
@ -537,7 +528,6 @@ The important bit in this file is the `ngExpressEngine` function:
这个文件中最重要的部分是 `ngExpressEngine` 函数:
<code-example path="universal/server.ts" title="server.ts" region="ngExpressEngine">
</code-example>
The `ngExpressEngine` is a wrapper around the universal's `renderModuleFactory` function that turns a client's requests into server-rendered HTML pages.
@ -641,7 +631,6 @@ You configure the Express server pipeline with calls to `app.get()` like this on
你通过通过调用 `app.get()` 来配置 Express 服务器的管道,就像下面这个数据请求一样:
<code-example path="universal/server.ts" title="server.ts (data URL)" region="data-request" linenums="false">
</code-example>
<div class="l-sub-section">
@ -688,7 +677,6 @@ The following code filters for request URLs with no extensions and treats them a
下列代码会过滤出不带扩展名的 URL并把它们当做导航请求进行处理。
<code-example path="universal/server.ts" title="server.ts (navigation)" region="navigation-request" linenums="false">
</code-example>
#### Serve static files safely
@ -710,7 +698,6 @@ The following express code routes all remaining requests to `/dist`; it returns
下列 Express 代码会把剩下的所有请求都路由到 `/dist` 目录下,如果文件未找到,就会返回 `404 - NOT FOUND`
<code-example path="universal/server.ts" title="server.ts (static files)" region="static" linenums="false">
</code-example>
{@a universal-configuration}
@ -734,7 +721,6 @@ Create a `tsconfig.server.json` file in the project root directory to configure
在项目的根目录下创建一个 `tsconfig.server.json` 文件来配置 TypeScript 和这个 Universal 应用的 AOT 编译选项。
<code-example path="universal/src/tsconfig.server.json" title="src/tsconfig.server.json">
</code-example>
This config extends from the root's `tsconfig.json` file. Certain settings are noteworthy for their differences.
@ -767,7 +753,6 @@ Create a `webpack.server.config.js` file in the project root directory with the
在项目的根目录下创建一个 `webpack.server.config.js` 文件,代码如下:
<code-example path="universal/webpack.server.config.js" title="webpack.server.config.js">
</code-example>
**Webpack configuration** is a rich topic beyond the scope of this guide.
@ -787,7 +772,6 @@ First add the _build_ and _serve_ commands to the `scripts` section of the `pack
首先把 `build``serve` 命令添加到 `package.json``scripts` 区:
<code-example format="." language="ts">
"scripts": {
...
"build:universal": "npm run build:client-and-server-bundles && npm run webpack:server",
@ -796,7 +780,6 @@ First add the _build_ and _serve_ commands to the `scripts` section of the `pack
"webpack:server": "webpack --config webpack.server.config.js --progress --colors"
...
}
</code-example>
{@a build}
@ -810,9 +793,7 @@ From the command prompt, type
在命令行提示中输入
<code-example format="." language="bash">
npm run build:universal
</code-example>
The Angular CLI compiles and bundles the universal app into two different folders, `browser` and `server`.
@ -832,9 +813,7 @@ After building the application, start the server.
构建完应用之后,启动服务器。
<code-example format="." language="bash">
npm run serve:universal
</code-example>
The console window should say
@ -842,9 +821,7 @@ The console window should say
在控制台窗口中应该看到
<code-example format="." language="bash">
Node server listening on http://localhost:4000
</code-example>
## Universal in action

View File

@ -282,7 +282,6 @@ architecture may look something like this:
AngularJS 中一个完全向 Angular 架构对齐过的组件型指令是这样的:
<code-example path="upgrade-module/src/app/hero-detail.directive.ts" title="hero-detail.directive.ts">
</code-example>
AngularJS 1.5 introduces the [component API](https://docs.angularjs.org/api/ng/type/angular.Module#component)
@ -310,7 +309,6 @@ using the component API:
如果使用这个组件 API 进行快捷定义,那么上面看到的组件型指令就变成了这样:
<code-example path="upgrade-module/src/app/upgrade-io/hero-detail.component.ts" region="hero-detail-io" title="hero-detail.component.ts">
</code-example>
Controller lifecycle hook methods `$onInit()`, `$onDestroy()`, and `$onChanges()`
@ -373,7 +371,6 @@ frameworks in how it actually works.
无论是在 AngularJS 中还是在 Angular 中,依赖注入都位于前沿和中心的位置,但在两个框架的工作原理上,却存在着一些关键的不同之处。
<table>
<tr>
<th>
@ -389,7 +386,6 @@ frameworks in how it actually works.
</th>
</tr>
<tr>
<td>
@ -411,7 +407,6 @@ frameworks in how it actually works.
</td>
</tr>
<tr>
<td>
@ -433,7 +428,6 @@ frameworks in how it actually works.
</td>
</tr>
</table>
Even accounting for these differences you can still have dependency injection
@ -529,9 +523,7 @@ where you use an Angular component from AngularJS like this:
考虑一个场景,你从 AngularJS 中使用一个 Angular 组件,就像这样:
<code-example language="html" escape="html">
&lt;a-component&gt;&lt;/a-component&gt;
</code-example>
The DOM element `<a-component>` will remain to be an AngularJS managed
@ -671,7 +663,6 @@ be used to bootstrap the AngularJS application.
在 AngularJS 应用中有一个 AngularJS 的根模块,它用于引导 AngularJS 应用。
<code-example path="upgrade-module/src/app/ajs-bootstrap/app.module.ts" region="ng1module" title="app.module.ts">
</code-example>
Pure AngularJS applications can be automatically bootstrapped by using an `ng-app`
@ -687,7 +678,6 @@ Say you have an `ng-app` driven bootstrap such as this one:
比如你现在有这样一个通过 `ng-app` 进行引导的应用:
<code-example path="upgrade-module/src/index-ng-app.html">
</code-example>
You can remove the `ng-app` and `ng-strict-di` directives from the HTML
@ -697,7 +687,6 @@ will result in the same thing:
你可以从 HTML 中移除 `ng-app``ng-strict-di` 指令,改为从 JavaScript 中调用 `angular.bootstrap`,它能达到同样效果:
<code-example path="upgrade-module/src/app/ajs-bootstrap/app.module.ts" region="bootstrap" title="app.module.ts">
</code-example>
To begin converting your AngularJS application to a hybrid, you need to load the Angular framework.
@ -713,7 +702,6 @@ and add a mapping for the `@angular/upgrade/static` package:
也可以通过 `npm install @angular/upgrade --save` 命令来安装 `@angular/upgrade` 包,并给它添加一个到 `@angular/upgrade/static` 包的映射。
<code-example path="upgrade-module/src/systemjs.config.1.js" region="upgrade-static-umd" title="systemjs.config.js (map)">
</code-example>
Next, create an `app.module.ts` file and add the following `NgModule` class:
@ -721,7 +709,6 @@ Next, create an `app.module.ts` file and add the following `NgModule` class:
接下来,创建一个 `app.module.ts` 文件,并添加下列 `NgModule` 类:
<code-example path="upgrade-module/src/app/ajs-a-hybrid-bootstrap/app.module.ts" region="ngmodule" title="app.module.ts">
</code-example>
This bare minimum `NgModule` imports `BrowserModule`, the module every Angular browser-based app must have.
@ -752,7 +739,6 @@ Now you can bootstrap `AppModule` using the `platformBrowserDynamic.bootstrapMod
现在,你就可以使用 `platformBrowserDynamic.bootstrapModule` 方法来启动 `AppModule` 了。
<code-example path="upgrade-module/src/app/ajs-a-hybrid-bootstrap/app.module.ts" region="bootstrap" title="app.module.ts'">
</code-example>
Congratulations! You're running a hybrid application! The
@ -779,7 +765,6 @@ Say you have a simple Angular component that shows information about a hero:
假设你有一个简单的用来显示英雄信息的 Angular 组件:
<code-example path="upgrade-module/src/app/downgrade-static/hero-detail.component.ts" title="hero-detail.component.ts">
</code-example>
If you want to use this component from AngularJS, you need to *downgrade* it
@ -790,7 +775,6 @@ using the `downgradeComponent()` method. The result is an AngularJS
其结果是一个 AngularJS 的*指令*,你可以把它注册到 AngularJS 的模块中:
<code-example path="upgrade-module/src/app/downgrade-static/app.module.ts" region="downgradecomponent" title="app.module.ts">
</code-example>
Because `HeroDetailComponent` is an Angular component, you must also add it to the
@ -806,7 +790,6 @@ NgModule.
将它加入到 Angular 模块的 `entryComponents` 列表中。
<code-example path="upgrade-module/src/app/downgrade-static/app.module.ts" region="ngmodule" title="app.module.ts">
</code-example>
<div class="l-sub-section">
@ -823,7 +806,6 @@ use like any other directive in AngularJS templates.
最终的结果是一个叫做 `heroDetail` 的 AngularJS 指令,你可以像用其它指令一样把它用在 AngularJS 模板中。
<code-example path="upgrade-module/src/index-downgrade-static.html" region="usecomponent">
</code-example>
<div class="alert is-helpful">
@ -847,7 +829,6 @@ like this:
Angular 的英雄详情组件带有像这样的输入属性与输出属性:
<code-example path="upgrade-module/src/app/downgrade-io/hero-detail.component.ts" title="hero-detail.component.ts">
</code-example>
These inputs and outputs can be supplied from the AngularJS template, and the
@ -856,7 +837,6 @@ These inputs and outputs can be supplied from the AngularJS template, and the
这些输入属性和输出属性的值来自于 AngularJS 的模板,而 `downgradeComponent()` 方法负责桥接它们:
<code-example path="upgrade-module/src/index-downgrade-io.html" region="usecomponent">
</code-example>
Note that even though you are in an AngularJS template, **you're using Angular
@ -880,9 +860,7 @@ of multiple words. In Angular, you would bind these attributes using camelCase:
它适用于由多个单词组成的输入或输出属性。在 Angular 中,你要使用小驼峰命名法绑定这些属性:
<code-example format="">
[myHero]="hero"
</code-example>
But when using them from AngularJS templates, you must use kebab-case:
@ -890,9 +868,7 @@ But when using them from AngularJS templates, you must use kebab-case:
但是从 AngularJS 的模板中使用它们时,你得使用中线命名法:
<code-example format="">
[my-hero]="hero"
</code-example>
</div>
@ -911,7 +887,6 @@ For example, you can easily make multiple copies of the component using `ng-repe
例如,你可以用 `ng-repeat` 简单的制作该组件的多份拷贝:
<code-example path="upgrade-module/src/index-downgrade-io.html" region="userepeatedcomponent">
</code-example>
### Using AngularJS Component Directives from Angular Code
@ -949,7 +924,6 @@ and a controller:
可升级组件的简单例子是只有一个模板和一个控制器的指令:
<code-example path="upgrade-module/src/app/upgrade-static/hero-detail.component.ts" region="hero-detail" title="hero-detail.component.ts">
</code-example>
You can *upgrade* this component to Angular using the `UpgradeComponent` class.
@ -963,11 +937,9 @@ All that is left is to add it to `AppModule`'s `declarations` array.
剩下是工作就是把它加入到 `AppModule``declarations` 数组。
<code-example path="upgrade-module/src/app/upgrade-static/hero-detail.component.ts" region="hero-detail-upgrade" title="hero-detail.component.ts">
</code-example>
<code-example path="upgrade-module/src/app/upgrade-static/app.module.ts" region="hero-detail-upgrade" title="app.module.ts">
</code-example>
<div class="alert is-helpful">
@ -992,7 +964,6 @@ observing the following rules:
当你从 Angular 模板中使用该组件时,就要使用**Angular 模板语法**来提供这些输入属性和输出属性,但要遵循下列规则:
<table>
<tr>
<th>
@ -1016,7 +987,6 @@ observing the following rules:
</th>
</tr>
<tr>
<th>
@ -1040,7 +1010,6 @@ observing the following rules:
</td>
</tr>
<tr>
<th>
@ -1064,7 +1033,6 @@ observing the following rules:
</td>
</tr>
<tr>
<th>
@ -1088,7 +1056,6 @@ observing the following rules:
</td>
</tr>
<tr>
<th>
@ -1117,7 +1084,6 @@ observing the following rules:
</td>
</tr>
</table>
For example, imagine a hero detail AngularJS component directive
@ -1126,7 +1092,6 @@ with one input and one output:
举个例子,假设 AngularJS 中有一个表示“英雄详情”的组件型指令,它带有一个输入属性和一个输出属性:
<code-example path="upgrade-module/src/app/upgrade-io/hero-detail.component.ts" region="hero-detail-io" title="hero-detail.component.ts">
</code-example>
You can upgrade this component to Angular, annotate inputs and outputs in the upgrade directive,
@ -1135,11 +1100,9 @@ and then provide the input and output using Angular template syntax:
你可以把这个组件升级到 Angular然后使用 Angular 的模板语法提供这个输入属性和输出属性:
<code-example path="upgrade-module/src/app/upgrade-io/hero-detail.component.ts" region="hero-detail-io-upgrade" title="hero-detail.component.ts">
</code-example>
<code-example path="upgrade-module/src/app/upgrade-io/container.component.ts" title="container.component.ts">
</code-example>
### Projecting AngularJS Content into Angular Components
@ -1164,7 +1127,6 @@ tag within them. Here's an example of such a component:
Angular 的组件通过使用 `<ng-content>` 标签来支持内容投影。下面是这类组件的一个例子:
<code-example path="upgrade-module/src/app/ajs-to-a-projection/hero-detail.component.ts" title="hero-detail.component.ts">
</code-example>
When using the component from AngularJS, you can supply contents for it. Just
@ -1175,7 +1137,6 @@ of the `<ng-content>` tag in Angular:
它们也在 Angular 中被投影到了 `<ng-content>` 标签所在的位置:
<code-example path="upgrade-module/src/index-ajs-to-a-projection.html" region="usecomponent">
</code-example>
<div class="alert is-helpful">
@ -1207,7 +1168,6 @@ point:
如果一个 AngularJS 组件型指令支持透传,它就会在自己的模板中使用 `ng-transclude` 指令标记出透传到的位置:
<code-example path="upgrade-module/src/app/a-to-ajs-transclusion/hero-detail.component.ts" title="hero-detail.component.ts">
</code-example>
If you upgrade this component and use it from Angular, you can populate
@ -1216,7 +1176,6 @@ the component tag with contents that will then get transcluded:
如果你升级这个组件,并把它用在 Angular 中,你就能把准备透传的内容放进这个组件的标签中。
<code-example path="upgrade-module/src/app/a-to-ajs-transclusion/container.component.ts" title="container.component.ts">
</code-example>
### Making AngularJS Dependencies Injectable to Angular
@ -1239,7 +1198,6 @@ code. For example, you might have a service called `HeroesService` in AngularJS:
比如,你可能在 AngularJS 中有一个名叫 `HeroesService` 的服务:
<code-example path="upgrade-module/src/app/ajs-to-a-providers/heroes.service.ts" title="heroes.service.ts">
</code-example>
You can upgrade the service using a Angular [factory provider](guide/dependency-injection#factory-providers)
@ -1260,11 +1218,9 @@ compilation can pick it up.
同时,建议导出 `heroesServiceFactory` 函数,以便 AOT 编译器可以拿到它们。
<code-example path="upgrade-module/src/app/ajs-to-a-providers/ajs-upgraded-providers.ts" title="ajs-upgraded-providers.ts">
</code-example>
<code-example path="upgrade-module/src/app/ajs-to-a-providers/app.module.ts" region="register" title="app.module.ts">
</code-example>
You can then inject it in Angular using its class as a type annotation:
@ -1306,7 +1262,6 @@ For example, you might have an Angular service called `Heroes`:
例如,你可能有一个 Angular 的 `Heroes` 服务:
<code-example path="upgrade-module/src/app/a-to-ajs-providers/heroes.ts" title="heroes.ts">
</code-example>
Again, as with Angular components, register the provider with the `NgModule` by adding it to the module's `providers` list.
@ -1314,7 +1269,6 @@ Again, as with Angular components, register the provider with the `NgModule` by
仿照 Angular 组件,把该提供商加入 `NgModule``providers` 列表中,以注册它。
<code-example path="upgrade-module/src/app/a-to-ajs-providers/app.module.ts" region="ngmodule" title="app.module.ts">
</code-example>
Now wrap the Angular `Heroes` in an *AngularJS factory function* using `downgradeInjectable()`
@ -1325,7 +1279,6 @@ The name of the AngularJS dependency is up to you:
依赖在 AngularJS 中的名字你可以自己定:
<code-example path="upgrade-module/src/app/a-to-ajs-providers/app.module.ts" region="register" title="app.module.ts">
</code-example>
After this, the service is injectable anywhere in AngularJS code:
@ -1333,7 +1286,6 @@ After this, the service is injectable anywhere in AngularJS code:
此后,该服务就能被注入到 AngularJS 代码中的任何地方了:
<code-example path="upgrade-module/src/app/a-to-ajs-providers/hero-detail.component.ts" title="hero-detail.component.ts">
</code-example>
## Using Ahead-of-time compilation with hybrid apps
@ -1362,7 +1314,6 @@ bootstrap the hybrid app:
你还要使用所生成的 `AppModuleFactory` 而不是原来的 `AppModule` 来引导一个混合式应用:
<code-example path="upgrade-phonecat-2-hybrid/app/main-aot.ts" title="app/main-aot.ts">
</code-example>
And that's all you need do to get the full benefit of AOT for Angular apps!
@ -1712,9 +1663,7 @@ Begin by installing TypeScript to the project.
先把 TypeScript 包安装到项目中。
<code-example format="">
npm i typescript --save-dev
</code-example>
Install type definitions for the existing libraries that
@ -1724,9 +1673,7 @@ Jasmine unit test framework.
还要为那些没有自带类型信息的库(比如 AngularJS 和 Jasmine安装类型定义文件。
<code-example format="">
npm install @types/jasmine @types/angular @types/angular-animate @types/angular-cookies @types/angular-mocks @types/angular-resource @types/angular-route @types/angular-sanitize --save-dev
</code-example>
You should also configure the TypeScript compiler with a `tsconfig.json` in the project directory
@ -1744,12 +1691,10 @@ JavaScript (based on the `tsconfig.json` configuration file):
最后,你应该把下列 npm 脚本添加到 `package.json` 中,用于把 TypeScript 文件编译成 JavaScript (根据 `tsconfig.json` 的配置):
<code-example format="">
"script": {
"tsc": "tsc",
"tsc:w": "tsc -w",
...
</code-example>
Now launch the TypeScript compiler from the command line in watch mode:
@ -1757,9 +1702,7 @@ Now launch the TypeScript compiler from the command line in watch mode:
现在,从命令行中用监视模式启动 TypeScript 编译器:
<code-example format="">
npm run tsc:w
</code-example>
Keep this process running in the background, watching and recompiling as you make changes.
@ -1813,7 +1756,6 @@ what the filter is supposed to do.
这可以更清楚的表明此过滤器打算做什么
<code-example path="upgrade-phonecat-1-typescript/app/core/checkmark/checkmark.filter.ts" title="app/core/checkmark/checkmark.filter.ts">
</code-example>
In the `Phone` service, you can explicitly annotate the `$resource` service dependency
@ -1822,7 +1764,6 @@ as an `angular.resource.IResourceService` - a type defined by the AngularJS typi
`Phone` 服务中,你可以明确的把 `$resource` 服务声明为 `angular.resource.IResourceService`,一个 AngularJS 类型定义提供的类型。
<code-example path="upgrade-phonecat-1-typescript/app/core/phone/phone.service.ts" title="app/core/phone/phone.service.ts">
</code-example>
You can apply the same trick to the application's route configuration file in `app.config.ts`,
@ -1833,7 +1774,6 @@ can verify you're calling their APIs with the correct kinds of arguments.
一旦为它们提供了类型信息TypeScript 就能检查你是否在用类型的正确参数来调用它们了。
<code-example path="upgrade-phonecat-1-typescript/app/app.config.ts" title="app/app.config.ts">
</code-example>
<div class="l-sub-section">
@ -1878,7 +1818,6 @@ Here's what the new class for the phone list component controller looks like:
新的“电话列表(phone list)”组件控制器类是这样的:
<code-example path="upgrade-phonecat-1-typescript/app/phone-list/phone-list.component.ts" title="app/phone-list/phone-list.component.ts">
</code-example>
What was previously done in the controller function is now done in the class
@ -1906,7 +1845,6 @@ that the user is looking at and another for the URL of the currently displayed i
在电话详情控制器中,你有两个成员:一个是用户正在查看的电话,另一个是正在显示的图像:
<code-example path="upgrade-phonecat-1-typescript/app/phone-detail/phone-detail.component.ts" title="app/phone-detail/phone-detail.component.ts">
</code-example>
This makes the controller code look a lot more like Angular already. You're
@ -1969,9 +1907,7 @@ Once these are done, run:
这些完成之后,就运行:
<code-example format="">
npm install
</code-example>
Soon you can load Angular dependencies into the application via `index.html`,
@ -1989,9 +1925,7 @@ instead of `app`:
`app/index.html` 移入项目的根目录,然后把 `package.json` 中的开发服务器根目录也指向项目的根目录,而不再是 `app` 目录:
<code-example format="">
"start": "http-server ./ -a localhost -p 8000 -c-1",
</code-example>
Now you're able to serve everything from the project root to the web browser. But you do *not*
@ -2002,7 +1936,6 @@ cause relative URLs to be resolved back to the `/app` directory:
现在,你就能把项目根目录下的每一样东西发给浏览器了。但你*不想*为了适应开发环境中的设置,被迫修改应用代码中用到的所有图片和数据的路径。因此,你要往 `index.html` 中添加一个 `<base>` 标签,它将导致各种相对路径被解析回 `/app` 目录:
<code-example path="upgrade-phonecat-2-hybrid/index.html" region="base" title="index.html">
</code-example>
Now you can load Angular via SystemJS. You'll add the Angular polyfills and the
@ -2013,7 +1946,6 @@ to load the actual application:
和 SystemJS 的配置加到 `<head>` 区的末尾,然后,你能就用 `System.import` 来加载实际的应用了:
<code-example path="upgrade-phonecat-2-hybrid/index.html" region="angular" title="index.html">
</code-example>
You also need to make a couple of adjustments
@ -2032,7 +1964,6 @@ and add a mapping for the `@angular/upgrade/static` package.
再通过 `npm install @angular/upgrade --save` 安装 `upgrade` 包,并为 `@angular/upgrade/static` 包添加一个映射。
<code-example path="upgrade-phonecat-2-hybrid/systemjs.config.1.js" region="paths" title="systemjs.config.js">
</code-example>
### Creating the _AppModule_
@ -2050,7 +1981,6 @@ The file contents remain:
文件的内容保留:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ajs.ts" title="app.module.ajs.ts">
</code-example>
Now create a new `app.module.ts` with the minimum `NgModule` class:
@ -2058,7 +1988,6 @@ Now create a new `app.module.ts` with the minimum `NgModule` class:
然后创建一个新的 `app.module.ts` 文件,其中是一个最小化的 `NgModule` 类:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="bare" title="app.module.ts">
</code-example>
### Bootstrapping a hybrid PhoneCat
@ -2086,7 +2015,6 @@ Then import `UpgradeModule` in the `AppModule`, and override its `ngDoBootstrap`
首先,从 `index.html` 中移除 `ng-app`。然后在 `AppModule` 中导入 `UpgradeModule`,并改写它的 `ngDoBootstrap` 方法:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="upgrademodule" title="app/app.module.ts">
</code-example>
Note that you are bootstrapping the AngularJS module from inside `ngDoBootstrap`.
@ -2104,7 +2032,6 @@ so it is already being loaded by the browser.
最后,在 `src/main.ts` 中引导这个 `AppModule`。该文件在 `systemjs.config.js` 中被配置为了应用的入口,所以它已经被加载进了浏览器中。
<code-example path="upgrade-phonecat-2-hybrid/app/main.ts" region="bootstrap" title="app/main.ts">
</code-example>
Now you're running both AngularJS and Angular at the same time. That's pretty
@ -2183,7 +2110,6 @@ Re-open the `app.module.ts` file, import and add `HttpModule` to the `imports` a
再次打开 `app.module.ts` 文件,导入并把 `HttpModule` 添加到 `AppModule``imports` 数组中:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="httpmodule" title="app.module.ts">
</code-example>
Now you're ready to upgrade the Phone service itself. Replace the ngResource-based
@ -2192,7 +2118,6 @@ service in `phone.service.ts` with a TypeScript class decorated as `@Injectable`
现在,你已经准备好了升级 `Phones` 服务本身。你将为 `phone.service.ts` 文件中基于 ngResource 的服务加上 `@Injectable` 装饰器:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="classdef" title="app/core/phone/phone.service.ts (skeleton)" linenums="false">
</code-example>
The `@Injectable` decorator will attach some dependency injection metadata
@ -2214,7 +2139,6 @@ and the other loads the details of a specified phone:
然后该服务在两个实例方法中被使用到,一个加载所有电话的列表,另一个加载一台指定电话的详情:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="fullclass" title="app/core/phone/phone.service.ts">
</code-example>
The methods now return Observables of type `PhoneData` and `PhoneData[]`. This is
@ -2224,7 +2148,6 @@ a type you don't have yet. Add a simple interface for it:
这是一个你从未用过的类型,因此你得为它新增一个简单的接口:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="phonedata-interface" title="app/core/phone/phone.service.ts (interface)" linenums="false">
</code-example>
`@angular/upgrade/static` has a `downgradeInjectable` method for the purpose of making
@ -2234,7 +2157,6 @@ Angular services available to AngularJS code. Use it to plug in the `Phone` serv
使用它来插入 `Phone` 服务:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="downgrade-injectable" title="app/core/phone/phone.service.ts (downgrade)" linenums="false">
</code-example>
Here's the full, final code for the service:
@ -2242,7 +2164,6 @@ Here's the full, final code for the service:
最终,该类的全部代码如下:
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" title="app/core/phone/phone.service.ts">
</code-example>
Notice that you're importing the `map` operator of the RxJS `Observable` separately.
@ -2258,7 +2179,6 @@ Because it's an Angular service, you register it with the `NgModule` providers:
因为它是 Angular 服务,你通过 `NgModule``providers` 数组来注册它:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="phone" title="app.module.ts">
</code-example>
Now that you are loading `phone.service.ts` through an import that is resolved
@ -2277,11 +2197,9 @@ it's really an instance of the `Phone` class and you annotate its type according
但它实际上是一个 `Phones` 类的实例,并且你可以据此注解它的类型:
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ajs.ts" title="app/phone-list/phone-list.component.ts">
</code-example>
<code-example path="upgrade-phonecat-2-hybrid/app/phone-detail/phone-detail.component.ajs.ts" title="app/phone-detail/phone-detail.component.ts">
</code-example>
Now there are two AngularJS components using an Angular service!
@ -2325,7 +2243,6 @@ You can then also remove the static `$inject` property from the class:
的组件了。然后,你还要从类中移除静态 `$inject` 属性。
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts" region="initialclass" title="app/phone-list/phone-list.component.ts">
</code-example>
The `selector` attribute is a CSS selector that defines where on the page the component
@ -2343,7 +2260,6 @@ with Angular's two-way `[(ngModel)]` binding syntax:
现在,将组件的模版也转换为 Angular 语法。在搜索控件中,把 AngularJS 的 `$ctrl` 表达式替换成 Angular 的双向绑定语法 `[(ngModel)]`
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="controls" title="app/phone-list/phone-list.template.html (search controls)" linenums="false">
</code-example>
Replace the list's `ng-repeat` with an `*ngFor` as
@ -2355,7 +2271,6 @@ Replace the image tag's `ng-src` with a binding to the native `src` property.
再把 `img` 标签的 `ng-src` 替换为一个标准的 `src` 属性(property)绑定。
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.template.html" region="list" title="app/phone-list/phone-list.template.html (phones)" linenums="false">
</code-example>
#### No Angular _filter_ or _orderBy_ filters
@ -2374,7 +2289,6 @@ which implements the filtering and ordering logic inside the component itself.
你把 `filter``orderBy` 过滤器改成绑定到控制器中的 `getPhones()` 方法,通过该方法,组件本身实现了过滤和排序逻辑。
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts" region="getphones" title="app/phone-list/phone-list.component.ts">
</code-example>
Now you need to downgrade the Angular component so you can use it in AngularJS.
@ -2391,7 +2305,6 @@ that the return value of the `downgradeComponent` method is a directive factory.
的返回值是一个指令工厂。
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts" region="downgrade-component" title="app/phone-list/phone-list.component.ts">
</code-example>
The new `PhoneListComponent` uses the Angular `ngModel` directive, located in the `FormsModule`.
@ -2403,7 +2316,6 @@ finally add it to `entryComponents` since you downgraded it:
最后,把降级的结果添加到 `entryComponents`中:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="phonelist" title="app.module.ts">
</code-example>
Remove the &lt;script&gt; tag for the phone list component from `index.html`.
@ -2415,7 +2327,6 @@ Now set the remaining `phone-detail.component.ts` as follows:
现在,剩下的 `phone-detail.component.ts` 文件变成了这样:
<code-example path="upgrade-phonecat-2-hybrid/app/phone-detail/phone-detail.component.ts" title="app/phone-detail/phone-detail.component.ts">
</code-example>
This is similar to the phone list component.
@ -2443,11 +2354,9 @@ Do that in a new file called `ajs-upgraded-providers.ts` and import it in `app.m
新建一个名叫 `ajs-upgraded-providers.ts` 的文件,并且在 `app.module.ts` 中导入它:
<code-example path="upgrade-phonecat-2-hybrid/app/ajs-upgraded-providers.ts" title="app/ajs-upgraded-providers.ts">
</code-example>
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="routeparams" title="app/app.module.ts ($routeParams)" linenums="false">
</code-example>
Convert the phone detail component template into Angular syntax as follows:
@ -2455,7 +2364,6 @@ Convert the phone detail component template into Angular syntax as follows:
把该组件的模板转变成 Angular 的语法,代码如下:
<code-example path="upgrade-phonecat-2-hybrid/app/phone-detail/phone-detail.template.html" title="app/phone-detail/phone-detail.template.html">
</code-example>
There are several notable changes here:
@ -2507,7 +2415,6 @@ Add `PhoneDetailComponent` component to the `NgModule` _declarations_ and _entry
`PhoneDetailComponent` 组件添加到 `NgModule`*declarations**entryComponents* 中:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="phonedetail" title="app.module.ts">
</code-example>
You should now also remove the phone detail component &lt;script&gt; tag from `index.html`.
@ -2536,7 +2443,6 @@ Rename the file to `checkmark.pipe.ts` to conform with Angular conventions:
把该文件改名成 `checkmark.pipe.ts`,以符合 Angular 中的命名约定:
<code-example path="upgrade-phonecat-2-hybrid/app/core/checkmark/checkmark.pipe.ts" title="app/core/checkmark/checkmark.pipe.ts" linenums="false">
</code-example>
Now import and declare the newly created pipe and
@ -2545,7 +2451,6 @@ remove the filter &lt;script&gt; tag from `index.html`:
现在,导入并声明这个新创建的管道,同时从 `index.html` 文件中移除该过滤器的`<script>` 标签:
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="checkmarkpipe" title="app.module.ts">
</code-example>
### AOT compile the hybrid app
@ -2563,7 +2468,6 @@ by the AOT compiler:
然后修改 `main-aot.ts` 的引导代码,通过所生成的 `AppComponentFactory` 来引导 AngularJS 应用:
<code-example path="upgrade-phonecat-2-hybrid/app/main-aot.ts" title="app/main-aot.ts">
</code-example>
You need to load all the AngularJS files you already use in `index.html` in `aot/index.html`
@ -2572,7 +2476,6 @@ as well:
你还要把在 `index.html` 中已经用到的所有 AngularJS 文件加载到 `aot/index.html` 中:
<code-example path="upgrade-phonecat-2-hybrid/aot/index.html" title="aot/index.html">
</code-example>
These files need to be copied together with the polyfills. The files the application
@ -2586,7 +2489,6 @@ Install `fs-extra` via `npm install fs-extra --save-dev` for better file copying
通过 `npm install fs-extra --save-dev` 安装 `fs-extra` 可以更好的复制文件,并且把 `copy-dist-files.js` 文件改成这样:
<code-example path="upgrade-phonecat-2-hybrid/copy-dist-files.js" title="copy-dist-files.js">
</code-example>
And that's all you need to use AOT while upgrading your app!
@ -2624,7 +2526,6 @@ Create a new `app.component.ts` file with the following `AppComponent` class:
创建新的 `app.component.ts` 文件,放入像这样的 `AppComponent` 类:
<code-example path="upgrade-phonecat-3-final/app/app.component.ts" title="app/app.component.ts">
</code-example>
It has a simple template that only includes the `<router-outlet>.
@ -2645,7 +2546,6 @@ It replaces the old AngularJS `ng-view` directive:
用它来代替 AngularJS 中的 `ng-view` 指令:
<code-example path="upgrade-phonecat-3-final/index.html" region="appcomponent" title="index.html (body)" linenums="false">
</code-example>
#### Create the _Routing Module_
@ -2664,7 +2564,6 @@ Angular 路由器配置的详情最好去查阅下[路由与导航](guide/router
它建议你创建一个专们用于路由器配置的 `NgModule`(名叫*路由模块*)。
<code-example path="upgrade-phonecat-3-final/app/app-routing.module.ts" title="app/app-routing.module.ts">
</code-example>
This module defines a `routes` object with two routes to the two phone components
@ -2693,7 +2592,6 @@ and the `UpgradeModule` import.
你还要从 `app.module.ts` 中移除调用 `ngDoBootstrap()` 来引导 AngularJS 模块的代码,以及对 `UpgradeModule` 的导入代码。
<code-example path="upgrade-phonecat-3-final/app/app.module.ts" title="app/app.module.ts">
</code-example>
And since you are routing to `PhoneListComponent` and `PhoneDetailComponent` directly rather than
@ -2714,7 +2612,6 @@ and let that directive construct the appropriate URL to the `PhoneDetailComponen
你可以通过把每个电话的 `id` 绑定到 `routerLink` 指令来生成它们了,该指令的构造函数会为 `PhoneDetailComponent` 生成正确的 URL
<code-example path="upgrade-phonecat-3-final/app/phone-list/phone-list.template.html" region="list" title="app/phone-list/phone-list.template.html (list with links)" linenums="false">
</code-example>
<div class="l-sub-section">
@ -2738,7 +2635,6 @@ Angular 路由器会传入不同的路由参数。
`ActivatedRoute.snapshot.params` 中提取出 `phoneId`,并像以前一样获取手机的数据:
<code-example path="upgrade-phonecat-3-final/app/phone-detail/phone-detail.component.ts" title="app/phone-detail/phone-detail.component.ts">
</code-example>
You are now running a pure Angular application!
@ -2766,7 +2662,6 @@ Switch the bootstrap method of the application from the `UpgradeModule` to the A
把应用的引导(`bootstrap`)方法从 `UpgradeAdapter` 的改为 Angular 的。
<code-example path="upgrade-phonecat-3-final/app/main.ts" title="main.ts">
</code-example>
If you haven't already, remove all references to the `UpgradeModule` from `app.module.ts`,
@ -2785,7 +2680,6 @@ in `entryComponents`.
因为你不再需要降级任何组件了,也不再需要把它们列在 `entryComponents` 中。
<code-example path="upgrade-phonecat-3-final/app/app.module.ts" title="app.module.ts">
</code-example>
You may also completely remove the following files. They are AngularJS
@ -2813,10 +2707,8 @@ The `@angular/upgrade` package and its mapping in `systemjs.config.js` can also
`systemjs.config.js` 中的 `@angular/upgrade` 包及其映射也可以移除了。
<code-example format="">
npm uninstall @angular/upgrade --save
npm uninstall @types/angular @types/angular-animate @types/angular-cookies @types/angular-mocks @types/angular-resource @types/angular-route @types/angular-sanitize --save-dev
</code-example>
Finally, from `index.html`, remove all references to AngularJS scripts and jQuery.
@ -2826,7 +2718,6 @@ When you're done, this is what it should look like:
当这些全部做完时,`index.html` 应该是这样的:
<code-example path="upgrade-phonecat-3-final/index.html" region="full" title="index.html">
</code-example>
That is the last you'll see of AngularJS! It has served us well but now
@ -2875,9 +2766,7 @@ Update the `protractor-conf.js` to sync with hybrid apps:
再对 `protractor-conf.js` 做下列修改,与混合应用同步:
<code-example format="">
ng12Hybrid: true
</code-example>
When you start to upgrade components and their templates to Angular, you'll make more changes
@ -2888,7 +2777,6 @@ For PhoneCat you need to make the following changes in order to make things work
这是因为 E2E 测试有一些匹配器是 AngularJS 中特有的。对于 PhoneCat 来说,为了让它能在 Angular 下工作,你得做下列修改:
<table>
<tr>
<th>
@ -2916,7 +2804,6 @@ For PhoneCat you need to make the following changes in order to make things work
</th>
</tr>
<tr>
<td>
@ -2940,7 +2827,6 @@ For PhoneCat you need to make the following changes in order to make things work
</td>
</tr>
<tr>
<td>
@ -2964,7 +2850,6 @@ For PhoneCat you need to make the following changes in order to make things work
</td>
</tr>
<tr>
<td>
@ -2988,7 +2873,6 @@ For PhoneCat you need to make the following changes in order to make things work
</td>
</tr>
<tr>
<td>
@ -3012,7 +2896,6 @@ For PhoneCat you need to make the following changes in order to make things work
</td>
</tr>
<tr>
<td>
@ -3036,7 +2919,6 @@ For PhoneCat you need to make the following changes in order to make things work
</td>
</tr>
</table>
When the bootstrap method is switched from that of `UpgradeModule` to
@ -3054,9 +2936,7 @@ Replace the `ng12Hybrid` previously added with the following in `protractor-conf
替换之前在 `protractor-conf.js` 中加入 `ng12Hybrid`,象这样:
<code-example format="">
useAllAngular2AppRoots: true,
</code-example>
Also, there are a couple of Protractor API calls in the PhoneCat test code that
@ -3069,7 +2949,6 @@ the redirection spec:
你就得把这些调用用一个 WebDriver 的通用 URL API 代替。第一个 API 是“重定向(redirect)”规约:
<code-example path="upgrade-phonecat-3-final/e2e-spec.ts" region="redirect" title="e2e-tests/scenarios.ts">
</code-example>
And the second is the phone links spec:
@ -3077,7 +2956,6 @@ And the second is the phone links spec:
然后是“电话链接(phone links)”规约:
<code-example path="upgrade-phonecat-3-final/e2e-spec.ts" region="links" title="e2e-tests/scenarios.ts">
</code-example>
### Unit Tests
@ -3103,7 +2981,6 @@ definitions of the AngularJS services you're consuming:
AngularJS 服务提供了类型定义。
<code-example path="upgrade-phonecat-1-typescript/app/phone-detail/phone-detail.component.spec.ts" title="app/phone-detail/phone-detail.component.spec.ts">
</code-example>
Once you start the upgrade process and bring in SystemJS, configuration changes
@ -3114,7 +2991,6 @@ which can be done with the following kind of shim file:
你需要让 SystemJS 加载所有的 Angular 新代码,
<code-example path="upgrade-phonecat-2-hybrid/karma-test-shim.1.js" title="karma-test-shim.js">
</code-example>
The shim first loads the SystemJS configuration, then Angular's test support libraries,
@ -3128,7 +3004,6 @@ as the base directory, instead of `app`.
然后需要修改 Karma 配置,来让它使用本应用的根目录作为基础目录(base directory),而不是 `app`
<code-example path="upgrade-phonecat-2-hybrid/karma.conf.ajs.js" region="basepath" title="karma.conf.js">
</code-example>
Once done, you can load SystemJS and other dependencies, and also switch the configuration
@ -3139,7 +3014,6 @@ the shim and SystemJS load them.
你要让这个 shim 文件和 SystemJS 去加载它们。
<code-example path="upgrade-phonecat-2-hybrid/karma.conf.ajs.js" region="files" title="karma.conf.js">
</code-example>
Since the HTML templates of Angular components will be loaded as well, you must help
@ -3148,7 +3022,6 @@ Karma out a bit so that it can route them to the right paths:
由于 Angular 组件中的 HTML 模板也同样要被加载,所以你得帮 Karma 一把,帮它在正确的路径下找到这些模板:
<code-example path="upgrade-phonecat-2-hybrid/karma.conf.ajs.js" region="html" title="karma.conf.js">
</code-example>
The unit test files themselves also need to be switched to Angular when their production
@ -3158,7 +3031,6 @@ as the pipe has no dependencies:
如果产品代码被切换到了 Angular单元测试文件本身也需要切换过来。对勾(checkmark)管道的规约可能是最简单的,因为它没有任何依赖:
<code-example path="upgrade-phonecat-2-hybrid/app/core/checkmark/checkmark.pipe.spec.ts" title="app/core/checkmark/checkmark.pipe.spec.ts">
</code-example>
The unit test for the phone service is a bit more involved. You need to switch from the mocked-out
@ -3167,7 +3039,6 @@ AngularJS `$httpBackend` to a mocked-out Angular Http backend.
`Phone` 服务的测试会牵扯到一点别的。你需要把模拟版的 AngularJS `$httpBackend` 服务切换到模拟板的 Angular Http 后端。
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.spec.ts" title="app/core/phone/phone.service.spec.ts">
</code-example>
For the component specs, you can mock out the `Phone` service itself, and have it provide
@ -3176,11 +3047,9 @@ canned phone data. You use Angular's component unit testing APIs for both compon
对于组件的规约,你可以模拟出 `Phone` 服务本身,并且让它提供电话的数据。你可以对这些组件使用 Angular 的组件单元测试 API。
<code-example path="upgrade-phonecat-2-hybrid/app/phone-detail/phone-detail.component.spec.ts" title="app/phone-detail/phone-detail.component.spec.ts">
</code-example>
<code-example path="upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.spec.ts" title="app/phone-list/phone-list.component.spec.ts">
</code-example>
Finally, revisit both of the component tests when you switch to the Angular
@ -3191,7 +3060,6 @@ instead of using the AngularJS `$routeParams`.
`RouteParams` 的 mock 对象,而不再用 AngularJS 中的 `$routeParams`
<code-example path="upgrade-phonecat-3-final/app/phone-detail/phone-detail.component.spec.ts" region="activatedroute" title="app/phone-detail/phone-detail.component.spec.ts">
</code-example>
And for the phone list component, a few adjustments to the router make
@ -3200,5 +3068,4 @@ the `RouteLink` directives work.
对于电话列表组件,还要再做少量的调整,以便路由器能让 `RouteLink` 指令正常工作。
<code-example path="upgrade-phonecat-3-final/app/phone-list/phone-list.component.spec.ts" region="routestuff" title="app/phone-list/phone-list.component.spec.ts">
</code-example>

View File

@ -125,9 +125,7 @@ Here's what the UI displays:
用户界面将显示:
<code-example>
a | ab | abc | ab | a | |
</code-example>
<figure>
@ -142,7 +140,6 @@ for `event.target.value` in which case the same user input would produce:
或者,你可以用 `event.key` 替代 `event.target.value`,积累各个按键本身,这样同样的用户输入可以产生:
<code-example>
a | b | c | backspace | backspace | backspace |
</code-example>
@ -428,7 +425,6 @@ values between data entry fields and model properties.
The next page, `Forms`, explains how to write
two-way bindings with `NgModel`.
这些技术对小规模演示很实用,但是在处理大量用户输入时,很容易变得累赘和笨拙。
要在数据录入字段和模型属性之间传递数据,双向数据绑定是更加优雅和简洁的方式。
下一章 ` 表单 ` 解释了如何用 `NgModel` 来进行双向绑定。

View File

@ -222,7 +222,7 @@ Include the files in the Visual Studio project as follows:
<h2 id='restore'>Step 4: Restore the required packages</h2>
<h2 id='restore'> 第四步: 恢复需要的包 </h2>
<h2 id='restore'>第四步: 恢复需要的包 </h2>
Restore the packages required for an Angular application as follows:
@ -348,7 +348,6 @@ rewrite rules near the bottom of the `web.config`:
通过把下列重写规则添加到 `web.config` 的底部,就可以告诉 Visual Studio 如何处理到应用页面的请求。
<code-example format='.'>
&lt;system.webServer&gt;
&lt;rewrite&gt;
&lt;rules&gt;
@ -399,5 +398,4 @@ The default browser opens and displays the QuickStart sample application.
Try editing any of the project files. Save and refresh the browser to
see the changes.
尝试编辑任何项目文件,*保存*并刷新浏览器来查看效果。

View File

@ -175,7 +175,6 @@ Then it **outputs** these files to the `app.js` _bundle file_ designated in conf
然后它把这些文件**输出**到当前配置所指定的*包文件*`app.js` 中:
<code-example name="webpack.config.js (single output)" language="javascript">
output: {
filename: 'app.js'
}
@ -204,7 +203,6 @@ Change the configuration so that it has two entry points, `main.ts` and `vendor.
所以要修改配置,以获得两个入口点:`main.ts` 和 `vendor.ts`
<code-example language="javascript">
entry: {
app: 'src/app.ts',
vendor: 'src/vendor.ts'
@ -257,7 +255,6 @@ Webpack 可以打包任何类型的文件JavaScript、TypeScript、CSS、SASS
再为 TypeScript 和 CSS 文件配置如下加载器。
<code-example language="javascript">
rules: [
{
test: /\.ts$/,
@ -277,7 +274,6 @@ it applies the `test` RegEx patterns.
当 Webpack 遇到如下所示的 `import` 语句时,它就会调用正则表达式的 `test` 方法。
<code-example language="typescript">
import { AppComponent } from './app.component.ts';
import 'uiframework/dist/uiframework.css';
@ -316,7 +312,6 @@ Webpack 有一条构建流水线,它被划分成多个经过精心定义的阶
可以把插件(比如 `uglify` 代码最小化插件)挂到流水线上:
<code-example language="javascript">
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
@ -342,7 +337,6 @@ Create a new project folder.
创建一个新的项目文件夹。
<code-example language="sh" class="code-shell">
mkdir angular-webpack
cd angular-webpack
@ -396,7 +390,6 @@ Open a terminal window and install the npm packages.
打开命令行窗口并安装这些 *npm*
<code-example language="sh" class="code-shell">
npm install
</code-example>
@ -530,7 +523,6 @@ You could write `import` statements with explicit extensions like this example:
如果你的应用程序只须 `import` 几十个 JavaScript 或 TypeScript 文件,而不是几百个,你可以在 `import` 语句里完整写上扩展名,如:
<code-example language="typescript">
import { AppComponent } from './app.component.ts';
</code-example>
@ -737,7 +729,6 @@ Grab the app code at the end of this guide and try:
抓取本指南底部的应用代码,并试一试:
<code-example language="sh" class="code-shell">
npm start
</code-example>
@ -746,11 +737,11 @@ Grab the app code at the end of this guide and try:
### Production configuration
### 产环境配置
### 产环境配置
Configuration of a *production* build resembles *development* configuration with a few key changes.
*产环境*下的配置和*开发环境*下的配置很相似……除了一些关键的改动。
*产环境*下的配置和*开发环境*下的配置很相似……除了一些关键的改动。
<code-example path="webpack/config/webpack.prod.js" title="config/webpack.prod.js" linenums="false">
@ -764,7 +755,7 @@ You won't deploy the artifacts needed only in development.
Put the production output bundle files in the `dist` folder.
把产环境的输出包放在 `dist` 目录下。
产环境的输出包放在 `dist` 目录下。
Webpack generates file names with cache-busting hash.
Thanks to the `HtmlWebpackPlugin`, you don't have to update the `index.html` file when the hash changes.
@ -809,7 +800,6 @@ Grab the app code at the end of this guide and try:
抓取本指南底部的应用代码,并试一试:
<code-example language="sh" class="code-shell">
npm run build
</code-example>
@ -826,7 +816,7 @@ You probably don't need to load and process the application-wide styles files fo
you'll use the `null` loader for those CSS files.
你并不需要使用很多配置项来运行单元测试。
也不需要在开发环境和产环境下引入的那些加载器和插件。
也不需要在开发环境和产环境下引入的那些加载器和插件。
如果有可能拖慢执行速度,甚至都不需要在单元测试中加载和处理应用全局样式文件,所以你用一个 `null` 加载器来处理所有 CSS。
You could merge the test configuration into the `webpack.common` configuration and override the parts you don't want or need.
@ -877,7 +867,6 @@ Grab the app code at the end of this guide and try:
抓取本指南底部的应用代码,并试一试:
<code-example language="sh" class="code-shell">
npm test
</code-example>
@ -1002,7 +991,7 @@ if the `CommonsChunkPlugin` hadn't detected the overlap and removed them from `a
You've learned just enough Webpack to configurate development, test and production builds
for a small Angular application.
你学到了刚好够用来在开发、测试、产环境下构建一个小型 Angular 应用的 Webpack 配置知识。
你学到了刚好够用来在开发、测试、产环境下构建一个小型 Angular 应用的 Webpack 配置知识。
_You could always do more_. Search the web for expert advice and expand your Webpack knowledge.
@ -1010,5 +999,4 @@ _You could always do more_. Search the web for expert advice and expand your Web
[Back to top](guide/webpack#top)
[回到顶部](guide/webpack#top)

View File

@ -421,7 +421,7 @@
},
{
"url": "guide/service-worker-devops",
"title": "环境下的 Service Worker",
"title": "产环境下的 Service Worker",
"tooltip": "使用 Service Worker 运行应用、管理应用更新、调试以及杀掉正在运行的应用。"
},
{

View File

@ -11,9 +11,7 @@
如果还没有安装 [Angular CLI](https://github.com/angular/angular-cli),请执行:
<code-example language="sh" class="code-shell">
npm install -g @angular/cli
</code-example>
## Create a new application
@ -25,9 +23,7 @@ Create a new project named `angular-tour-of-heroes` with this CLI command.
使用 CLI 命令创建一个名叫 `angular-tour-of-heroes` 的新项目。
<code-example language="sh" class="code-shell">
ng new angular-tour-of-heroes
</code-example>
The Angular CLI generated a new project with a default application and supporting files.
@ -43,10 +39,8 @@ Go to the project directory and launch the application.
进入项目目录,并启动这个应用。
<code-example language="sh" class="code-shell">
cd angular-tour-of-heroes
ng serve --open
</code-example>
<div class="l-sub-section">
@ -111,7 +105,6 @@ Open the component class file (`app.component.ts`) and change the value of the `
打开组件的类文件 (`app.component.ts`),并把 `title` 属性的值修改为 'Tour of Heroes' (英雄指南)。
<code-example path="toh-pt0/src/app/app.component.ts" region="set-title" title="app.component.ts (class title property)" linenums="false">
</code-example>
Open the component template file (`app.component.html`) and
@ -122,7 +115,6 @@ Replace it with the following line of HTML.
<code-example path="toh-pt0/src/app/app.component.html"
title="app.component.html (template)" linenums="false">
</code-example>
The double curly braces are Angular's *interpolation binding* syntax.
@ -155,7 +147,6 @@ Here's an excerpt from the `styles.css` for the _Tour of Heroes_ sample app.
下面是这个*英雄指南*范例应用中 `styles.css` 文件的片段。
<code-example path="toh-pt0/src/styles.1.css" title="src/styles.css (excerpt)">
</code-example>
## Final code review
@ -183,7 +174,6 @@ Here are the code files discussed on this page.
title="src/styles.css (excerpt)"
path="toh-pt0/src/styles.1.css">
</code-pane>
</code-tabs>
## Summary

View File

@ -18,9 +18,7 @@ Using the Angular CLI, generate a new component named `heroes`.
使用 Angular CLI 创建一个名为 `heroes` 的新组件。
<code-example language="sh" class="code-shell">
ng generate component heroes
</code-example>
The CLI creates a new folder, `src/app/heroes/` and generates
@ -35,7 +33,6 @@ The `HeroesComponent` class file is as follows:
<code-example
path="toh-pt1/src/app/heroes/heroes.component.ts" region="v1"
title="app/heroes/heroes.component.ts (initial version)" linenums="false">
</code-example>
You always import the `Component` symbol from the Angular core library
@ -89,7 +86,6 @@ Add a `hero` property to the `HeroesComponent` for a hero named "Windstorm."
`HeroesComponent` 中添加一个 `hero` 属性,用来表示一个名叫 “Windstorm” 的英雄。
<code-example path="toh-pt1/src/app/heroes/heroes.component.ts" region="add-hero" title="heroes.component.ts (hero property)" linenums="false">
</code-example>
### Show the hero
@ -103,7 +99,6 @@ replace it with a data binding to the new `hero` property.
打开模板文件 `heroes.component.html`。删除 Angular CLI 自动生成的默认内容,改为到 `hero` 属性的数据绑定。
<code-example path="toh-pt1/src/app/heroes/heroes.component.1.html" title="heroes.component.html" region="show-hero-1" linenums="false">
</code-example>
## Show the _HeroesComponent_ view
@ -121,7 +116,6 @@ So add an `<app-heroes>` element to the `AppComponent` template file, just below
所以,只要把 `<app-heroes>` 元素添加到 `AppComponent` 的模板文件中就可以了,就放在标题下方。
<code-example path="toh-pt1/src/app/app.component.html" title="src/app/app.component.html" linenums="false">
</code-example>
Assuming that the CLI `ng serve` command is still running,
@ -143,7 +137,6 @@ Give it `id` and `name` properties.
`src/app` 文件夹中为 `Hero` 类创建一个文件,并添加 `id``name` 属性。
<code-example path="toh-pt1/src/app/hero.ts" title="src/app/hero.ts" linenums="false">
</code-example>
Return to the `HeroesComponent` class and import the `Hero` class.
@ -162,7 +155,6 @@ The revised `HeroesComponent` class file should look like this:
<code-example path="toh-pt1/src/app/heroes/heroes.component.ts" linenums="false"
title= "src/app/heroes/heroes.component.ts">
</code-example>
The page no longer displays properly because you changed the hero from a string to an object.
@ -182,7 +174,6 @@ and show both `id` and `name` in a details layout like this:
path="toh-pt1/src/app/heroes/heroes.component.1.html"
region="show-hero-2"
title="heroes.component.html (HeroesComponent's template)" linenums="false">
</code-example>
The browser refreshes and display's the hero's information.
@ -200,7 +191,6 @@ Modify the `hero.name` binding like this.
<code-example
path="toh-pt1/src/app/heroes/heroes.component.html"
region="pipe">
</code-example>
The browser refreshes and now the hero's name is displayed in capital letters.
@ -273,10 +263,8 @@ for a message like
打开浏览器的开发工具,就会在控制台中看到如下信息:
<code-example language="sh" class="code-shell">
Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.
</code-example>
Although `ngModel` is a valid Angular directive, it isn't available by default.
@ -322,7 +310,6 @@ Open `AppModule` (`app.module.ts`) and import the `FormsModule` symbol from the
<code-example path="toh-pt1/src/app/app.module.ts" title="app.module.ts (FormsModule symbol import)"
region="formsmodule-js-import">
</code-example>
Then add `FormsModule` to the `@NgModule` metadata's `imports` array, which contains a list of external modules that the app needs.
@ -331,7 +318,6 @@ Then add `FormsModule` to the `@NgModule` metadata's `imports` array, which cont
<code-example path="toh-pt1/src/app/app.module.ts" title="app.module.ts ( @NgModule imports)"
region="ng-imports">
</code-example>
When the browser refreshes, the app should work again. You can edit the hero's name and see the changes reflected immediately in the `<h2>` above the textbox.
@ -360,7 +346,6 @@ Open `src/app/app.module.ts` and find `HeroesComponent` imported near the top.
打开 `src/app/app.module.ts` 你就会发现 `HeroesComponent` 已经在顶部导入过了。
<code-example path="toh-pt1/src/app/app.module.ts" region="heroes-import" >
</code-example>
The `HeroesComponent` is declared in the `@NgModule.declarations` array.
@ -368,7 +353,6 @@ The `HeroesComponent` is declared in the `@NgModule.declarations` array.
`HeroesComponent` 也已经声明在了 `@NgModule.declarations` 数组中。
<code-example path="toh-pt1/src/app/app.module.ts" region="declarations">
</code-example>
Note that `AppModule` declares both application components, `AppComponent` and `HeroesComponent`.

View File

@ -32,7 +32,6 @@ The file should look like this.
<code-example path="toh-pt2/src/app/mock-heroes.ts" linenums="false"
title="src/app/mock-heroes.ts">
</code-example>
## Displaying heroes
@ -48,7 +47,6 @@ Open the `HeroesComponent` class file and import the mock `HEROES`.
打开 `HeroesComponent` 类文件,并导入模拟的 `HEROES`
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="import-heroes" title="src/app/heroes/heroes.component.ts (import HEROES)">
</code-example>
Add a `heroes` property to the class that exposes these heroes for binding.
@ -56,7 +54,6 @@ Add a `heroes` property to the class that exposes these heroes for binding.
往类中添加一个 `heroes` 属性,这样可以暴露出这些英雄,以供绑定。
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="heroes">
</code-example>
### List heroes with _*ngFor_
@ -88,7 +85,6 @@ Make it look like this:
做完之后应该是这样的:
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="list" title="heroes.component.html (heroes template)" linenums="false">
</code-example>
Now change the `<li>` to this:
@ -96,7 +92,6 @@ Now change the `<li>` to this:
现在,把 `<li>` 修改成这样:
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="li">
</code-example>
The [`*ngFor`](guide/template-syntax#ngFor) is Angular's _repeater_ directive.
@ -176,7 +171,6 @@ and pointed to it in `@Component.styleUrls` like this.
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="metadata"
title="src/app/heroes/heroes.component.ts (@Component)">
</code-example>
Open the `heroes.component.css` file and paste in the private CSS styles for the `HeroesComponent`.
@ -218,7 +212,6 @@ Add a click event binding to the `<li>` like this:
再往 `<li>` 元素上插入一句点击事件的绑定代码:
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="selectedHero-click" title="heroes.component.html (template excerpt)" linenums="false">
</code-example>
This is an example of Angular's [event binding](guide/template-syntax#event-binding) syntax.
@ -254,7 +247,6 @@ to the component's `selectedHero`.
添加如下 `onSelect()` 方法,它会把模板中被点击的英雄赋值给组件的 `selectedHero` 属性。
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="on-select" title="src/app/heroes/heroes.component.ts (onSelect)" linenums="false">
</code-example>
### Update the details template
@ -268,7 +260,6 @@ Rename `hero` to `selectedHero`.
`hero` 改名为 `selectedHero`
<code-example path="toh-pt2/src/app/heroes/heroes.component.html" region="selectedHero-details" title="heroes.component.html (selected hero details)" linenums="false">
</code-example>
### Hide empty details with _*ngIf_
@ -284,9 +275,7 @@ Open the browser developer tools and look in the console for an error message li
打开浏览器的开发者工具,它的控制台中显示出如下错误信息:
<code-example language="sh" class="code-shell">
HeroesComponent.html:3 ERROR TypeError: Cannot read property 'name' of undefined
</code-example>
Now click one of the list items.
@ -332,7 +321,6 @@ Don't forget the asterisk (*) in front of `ngIf`. It's a critical part of the sy
</div>
<code-example path="toh-pt2/src/app/heroes/heroes.component.html" region="ng-if" title="src/app/heroes/heroes.component.html (*ngIf)" linenums="false">
</code-example>
After the browser refreshes, the list of names reappears.
@ -391,7 +379,6 @@ Add the following `[class.selected]` binding to the `<li>` in the `HeroesCompon
`HeroesComponent` 模板中的 `<li>` 元素上添加 `[class.selected]` 绑定,代码如下:
<code-example path="toh-pt2/src/app/heroes/heroes.component.1.html" region="class-selected" title="heroes.component.html (toggle the 'selected' CSS class)" linenums="false">
</code-example>
When the current row hero is the same as the `selectedHero`, Angular adds the `selected` CSS class. When the two heroes are different, Angular removes the class.
@ -421,7 +408,6 @@ Here are the code files discussed on this page, including the `HeroesComponent`
下面是本页面中所提及的代码文件,包括 `HeroesComponent` 的样式。
<code-tabs>
<code-pane title="src/app/heroes/heroes.component.ts" path="toh-pt2/src/app/heroes/heroes.component.ts">
</code-pane>
@ -430,7 +416,6 @@ Here are the code files discussed on this page, including the `HeroesComponent`
<code-pane title="src/app/heroes/heroes.component.css" path="toh-pt2/src/app/heroes/heroes.component.css">
</code-pane>
</code-tabs>
## Summary

View File

@ -12,12 +12,12 @@ You'll want to split up large components into smaller sub-components, each focus
把所有特性都放在同一个组件中,将会使应用“长大”后变得不可维护。
你要把大型组件拆分成小一点的子组件,每个子组件都要集中精力处理某个特定的任务或工作流。
In this page, you'll take the first step in that direction by moving the hero details into a separate, reusable `HeroDetailComponent`.
In this page, you'll take the first step in that direction by moving the hero details into a separate, reusable `HeroDetailsComponent`.
本页面中,你将迈出第一步 —— 把英雄详情移入一个独立的、可复用的 `HeroDetailComponent`
The `HeroesComponent` will only present the list of heroes.
The `HeroDetailComponent` will present details of a selected hero.
The `HeroDetailsComponent` will present details of a selected hero.
`HeroesComponent` 将仅仅用来表示英雄列表。
`HeroDetailComponent` 将用来表示所选英雄的详情。
@ -31,9 +31,7 @@ Use the Angular CLI to generate a new component named `hero-detail`.
使用 Angular CLI 生成一个名叫 `hero-detail` 的新组件。
<code-example language="sh" class="code-shell">
ng generate component hero-detail
</code-example>
The command scaffolds the `HeroDetailComponent` files and declares the component in `AppModule`.
@ -78,7 +76,6 @@ Open the `HeroDetailComponent` class file and import the `Hero` symbol.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts"
region="import-hero" title="src/app/hero-detail/hero-detail.component.ts (import Hero)">
</code-example>
The `hero` property
@ -89,7 +86,6 @@ because the _external_ `HeroesComponent` [will bind to it](#heroes-component-tem
`hero` 属性[必须是一个带有 `@Input()` 装饰器的输入属性](guide/template-syntax#inputs-outputs "Input and Output properties"),因为*外部的* `HeroesComponent` 组件[将会绑定到它](#heroes-component-template)。就像这样:
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding">
</code-example>
Amend the `@angular/core` import statement to include the `Input` symbol.
@ -97,7 +93,6 @@ Amend the `@angular/core` import statement to include the `Input` symbol.
修改 `@angular/core` 的导入语句,导入 `Input` 符号。
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" region="import-input" title="src/app/hero-detail/hero-detail.component.ts (import Input)" linenums="false">
</code-example>
Add a `hero` property, preceded by the `@Input()` decorator.
@ -105,7 +100,6 @@ Add a `hero` property, preceded by the `@Input()` decorator.
添加一个带有 `@Input()` 装饰器的 `hero` 属性。
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" region="input-hero" linenums="false">
</code-example>
That's the only change you should make to the `HeroDetailComponent` class.
@ -181,7 +175,6 @@ The revised `HeroesComponent` template should look like this:
<code-example path="toh-pt3/src/app/heroes/heroes.component.html"
title="heroes.component.html" linenums="false">
</code-example>
The browser refreshes and the app starts working again as it did before.
@ -258,4 +251,3 @@ to make the `hero` property available for binding
by the external `HeroesComponent`.
你用 [`@Input` 装饰器](guide/template-syntax#inputs-outputs)来让 `hero` 属性可以在外部的 `HeroesComponent` 中绑定。

View File

@ -52,9 +52,7 @@ Using the Angular CLI, create a service called `hero`.
使用 Angular CLI 创建一个名叫 `hero` 的服务。
<code-example language="sh" class="code-shell">
ng generate service hero
</code-example>
The command generates skeleton `HeroService` class in `src/app/hero.service.ts`
@ -65,7 +63,6 @@ The `HeroService` class should look like the below.
<code-example path="toh-pt4/src/app/hero.service.1.ts" region="new"
title="src/app/hero.service.ts (new service)" linenums="false">
</code-example>
### _@Injectable()_ services
@ -118,7 +115,6 @@ Import the `Hero` and `HEROES`.
导入 `Hero``HEROES`
<code-example path="toh-pt4/src/app/hero.service.ts" region="import-heroes">
</code-example>
Add a `getHeroes` method to return the _mock heroes_.
@ -126,7 +122,6 @@ Add a `getHeroes` method to return the _mock heroes_.
添加一个 `getHeroes` 方法,让它返回*模拟的英雄列表*。
<code-example path="toh-pt4/src/app/hero.service.1.ts" region="getHeroes">
</code-example>
{@a provide}
@ -158,9 +153,7 @@ by appending `--module=app`.
这是一个常用的选择,因此你可以通过 `--module=app` 选项让 CLI 自动把它提供给 `AppModule`
<code-example language="sh" class="code-shell">
ng generate service hero --module=app
</code-example>
Since you did not, you'll have to provide it yourself.
@ -172,7 +165,6 @@ Open the `AppModule` class, import the `HeroService`, and add it to the `@NgModu
打开 `AppModule` 类,导入 `HeroService`,并把它加入 `@NgModule.providers` 数组中。
<code-example path="toh-pt4/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (providers)" region="providers-heroservice">
</code-example>
The `providers` array tells Angular to create a single, shared instance of `HeroService`
@ -215,7 +207,6 @@ Import the `HeroService` instead.
转而导入 `HeroService`
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" title="src/app/heroes/heroes.component.ts (import HeroService)" region="hero-service-import">
</code-example>
Replace the definition of the `heroes` property with a simple declaration.
@ -223,7 +214,6 @@ Replace the definition of the `heroes` property with a simple declaration.
`heroes` 属性的定义改为一句简单的声明。
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" region="heroes">
</code-example>
{@a inject}
@ -237,7 +227,6 @@ Add a private `heroService` parameter of type `HeroService` to the constructor.
往构造函数中添加一个私有的 `heroService`,其类型为 `HeroService`
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" region="ctor">
</code-example>
The parameter simultaneously defines a private `heroService` property and identifies it as a `HeroService` injection site.
@ -258,7 +247,6 @@ Create a function to retrieve the heroes from the service.
创建一个函数,以从服务中获取这些英雄数据。
<code-example path="toh-pt4/src/app/heroes/heroes.component.1.ts" region="getHeroes">
</code-example>
{@a oninit}
@ -285,7 +273,6 @@ let Angular call `ngOnInit` at an appropriate time _after_ constructing a `Heroe
你应该改为在 [*ngOnInit 生命周期钩子*](guide/lifecycle-hooks)中调用 `getHeroes()`,并且等 Angular 构造出 `HeroesComponent` 的实例之后,找个恰当的时机调用 `ngOnInit`
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" region="ng-on-init">
</code-example>
### See it run
@ -311,7 +298,6 @@ as if heroes could be fetched synchronously.
`HeroesComponent` 也同样假设能同步取到 `getHeroes()` 的结果。
<code-example path="toh-pt4/src/app/heroes/heroes.component.1.ts" region="get-heroes">
</code-example>
This will not work in a real app.
@ -365,7 +351,6 @@ Open the `HeroService` file and import the `Observable` and `of` symbols from Rx
<code-example path="toh-pt4/src/app/hero.service.ts"
title="src/app/hero.service.ts (Observable imports)" region="import-observable">
</code-example>
Replace the `getHeroes` method with this one.
@ -478,9 +463,7 @@ Use the CLI to create the `MessagesComponent`.
使用 CLI 创建 `MessagesComponent`
<code-example language="sh" class="code-shell">
ng generate component messages
</code-example>
The CLI creates the component files in the `src/app/messages` folder and declare `MessagesComponent` in `AppModule`.
@ -494,7 +477,6 @@ Modify the `AppComponent` template to display the generated `MessagesComponent`
<code-example
title = "/src/app/app.component.html"
path="toh-pt4/src/app/app.component.html">
</code-example>
You should see the default paragraph from `MessagesComponent` at the bottom of the page.
@ -512,9 +494,7 @@ The `--module=app` option tells the CLI to [_provide_ this service](#provide) i
`--module=app` 选项告诉 CLI 在 `AppModule` 中[提供这个服务](#provide)。
<code-example language="sh" class="code-shell">
ng generate service message --module=app
</code-example>
Open `MessageService` and replace its contents with the following.
@ -524,7 +504,6 @@ Open `MessageService` and replace its contents with the following.
<code-example
title = "/src/app/message.service.ts"
path="toh-pt4/src/app/message.service.ts">
</code-example>
The service exposes its cache of `messages` and two methods: one to `add()` a message to the cache and another to `clear()` the cache.
@ -544,7 +523,6 @@ Re-open the `HeroService` and import the `MessageService`.
<code-example
title = "/src/app/hero.service.ts (import MessageService)"
path="toh-pt4/src/app/hero.service.ts" region="import-message-service">
</code-example>
Modify the constructor with a parameter that declares a private `messageService` property.
@ -556,7 +534,6 @@ Angular 将会在创建 `HeroService` 时把 `MessageService` 的单例注入到
<code-example
path="toh-pt4/src/app/hero.service.ts" region="ctor">
</code-example>
<div class="l-sub-section">
@ -578,7 +555,6 @@ Modify the `getHeroes` method to send a message when the heroes are fetched.
修改 `getHeroes` 方法,在获取到英雄数组时发送一条消息。
<code-example path="toh-pt4/src/app/hero.service.ts" region="getHeroes">
</code-example>
### Display the message from `HeroService`
@ -598,19 +574,17 @@ Open `MessagesComponent` and import the `MessageService`.
<code-example
title = "/src/app/messages/messages.component.ts (import MessageService)"
path="toh-pt4/src/app/messages/messages.component.ts" region="import-message-service">
</code-example>
Modify the constructor with a parameter that declares a **public** `messageService` property.
Angular will inject the singleton `MessageService` into that property
when it creates the `MessagesComponent`.
when it creates the `HeroService`.
修改构造函数,添加一个 **public**`messageService` 属性。
Angular 将会在创建 `MessagesComponent` 的实例时 把 `MessageService` 的实例注入到这个属性中。
<code-example
path="toh-pt4/src/app/messages/messages.component.ts" region="ctor">
</code-example>
The `messageService` property **must be public** because you're about to bind to it in the template.
@ -636,7 +610,6 @@ Replace the CLI-generated `MessagesComponent` template with the following.
<code-example
title = "src/app/messages/messages.component.html"
path="toh-pt4/src/app/messages/messages.component.html">
</code-example>
This template binds directly to the component's `messageService`.

View File

@ -50,9 +50,7 @@ Use the CLI to generate it.
使用 CLI 生成它。
<code-example language="sh" class="code-shell">
ng generate module app-routing --flat --module=app
</code-example>
<div class="l-sub-section">
@ -71,7 +69,6 @@ The generated file looks like this:
<code-example path="toh-pt5/src/app/app-routing.module.0.ts"
title="src/app/app-routing.module.ts (generated)">
</code-example>
You generally don't declare components in a routing module so you can delete the
@ -98,7 +95,6 @@ in the `AppModule` components that will need them.
<code-example path="toh-pt5/src/app/app-routing.module.ts"
region="v1"
title="src/app/app-routing.module.ts (v1)">
</code-example>
### Add routes
@ -134,7 +130,6 @@ Then define an array of routes with a single `route` to that component.
<code-example path="toh-pt5/src/app/app-routing.module.ts"
region="heroes-route">
</code-example>
Once you've finished setting up, the router will match that URL to `path: 'heroes'`
@ -157,7 +152,6 @@ configure it with the `routes` in one step by calling
<code-example path="toh-pt5/src/app/app-routing.module.ts"
region="ngmodule-imports">
</code-example>
<div class="l-sub-section">
@ -182,7 +176,6 @@ Open the `AppComponent` template replace the `<app-heroes>` element with a `<rou
<code-example path="toh-pt5/src/app/app.component.html"
region="outlet"
title="src/app/app.component.html (router-outlet)">
</code-example>
You removed `<app-heroes>` because you will only display the `HeroesComponent` when the user navigates to it.
@ -211,9 +204,7 @@ You should still be running with this CLI command.
你的 CLI 命令应该仍在运行吧。
<code-example language="sh" class="code-shell">
ng serve
</code-example>
The browser should refresh and display the app title but not the list of heroes.
@ -255,7 +246,6 @@ The revised `AppComponent` template looks like this:
path="toh-pt5/src/app/app.component.html"
region="heroes"
title="src/app/app.component.html (heroes RouterLink)">
</code-example>
A [`routerLink` attribute](#routerlink) is set to `"/heroes"`,
@ -301,9 +291,7 @@ Add a `DashboardComponent` using the CLI:
使用 CLI 添加一个 `DashboardComponent`
<code-example language="sh" class="code-shell">
ng generate component dashboard
</code-example>
The CLI generates the files for the `DashboardComponent` and declares it in `AppModule`.
@ -315,7 +303,6 @@ Replace the default file content in these three files as follows and then return
把这三个文件中的内容改成这样,并回来做一个随堂讨论:
<code-tabs>
<code-pane
title="src/app/dashboard/dashboard.component.html" path="toh-pt5/src/app/dashboard/dashboard.component.1.html">
</code-pane>
@ -327,7 +314,6 @@ Replace the default file content in these three files as follows and then return
<code-pane
title="src/app/dashboard/dashboard.component.css" path="toh-pt5/src/app/dashboard/dashboard.component.css">
</code-pane>
</code-tabs>
The _template_ presents a grid of hero name links.
@ -368,7 +354,6 @@ This `getHeroes` reduces the number of heroes displayed to four
这个 `getHeroes` 函数把要显示的英雄的数量缩减为四个(第二、第三、第四、第五)。
<code-example path="toh-pt5/src/app/dashboard/dashboard.component.ts" region="getHeroes">
</code-example>
### Add the dashboard route
@ -387,7 +372,6 @@ Import the `DashboardComponent` in the `AppRoutingModule`.
path="toh-pt5/src/app/app-routing.module.ts"
region="import-dashboard"
title="src/app/app-routing.module.ts (import DashboardComponent)">
</code-example>
Add a route to the `AppRoutingModule.routes` array that matches a path to the `DashboardComponent`.
@ -397,7 +381,6 @@ Add a route to the `AppRoutingModule.routes` array that matches a path to the `D
<code-example
path="toh-pt5/src/app/app-routing.module.ts"
region="dashboard-route">
</code-example>
### Add a default route
@ -418,7 +401,6 @@ route to the `AppRoutingModule.Routes` array.
要让应用自动导航到这个仪表盘,请把下列路由添加到 `AppRoutingModule.Routes` 数组中。
<code-example path="toh-pt5/src/app/app-routing.module.ts" region="redirect-route">
</code-example>
This route redirects a URL that fully matches the empty path to the route whose path is `'/dashboard'`.
@ -445,7 +427,6 @@ Add a dashboard navigation link to the `AppComponent` shell template, just above
把仪表盘的导航链接添加到壳组件 `AppComponent` 的模板中,就放在 *Heroes* 链接的前面。
<code-example path="toh-pt5/src/app/app.component.html" title="src/app/app.component.html">
</code-example>
After the browser refreshes you can navigate freely between the two views by clicking the links.
@ -523,7 +504,6 @@ Open `AppRoutingModule` and import `HeroDetailComponent`.
path="toh-pt5/src/app/app-routing.module.ts"
region="import-herodetail"
title="src/app/app-routing.module.ts (import HeroDetailComponent)">
</code-example>
Then add a _parameterized_ route to the `AppRoutingModule.routes` array that matches the path pattern to the _hero detail_ view.
@ -533,7 +513,6 @@ Then add a _parameterized_ route to the `AppRoutingModule.routes` array that mat
<code-example
path="toh-pt5/src/app/app-routing.module.ts"
region="detail-route">
</code-example>
The colon (:) in the `path` indicates that `:id` is a placeholder for a specific hero `id`.
@ -548,7 +527,6 @@ At this point, all application routes are in place.
path="toh-pt5/src/app/app-routing.module.ts"
region="routes"
title="src/app/app-routing.module.ts (all routes)">
</code-example>
### `DashboardComponent` hero links
@ -569,7 +547,6 @@ fix the dashboard hero links to navigate via the _parameterized_ dashboard route
path="toh-pt5/src/app/dashboard/dashboard.component.html"
region="click"
title="src/app/dashboard/dashboard.component.html (hero links)">
</code-example>
You're using Angular [interpolation binding](guide/template-syntax#interpolation) within the `*ngFor` repeater
@ -593,7 +570,6 @@ are bound to the component's `onSelect()` method.
path="toh-pt4/src/app/heroes/heroes.component.html"
region="list"
title="src/app/heroes/heroes.component.html (list with onSelect)">
</code-example>
Strip the `<li>` back to just its `*ngFor`,
@ -608,7 +584,6 @@ is the same as in the dashboard template
path="toh-pt5/src/app/heroes/heroes.component.html"
region="list"
title="src/app/heroes/heroes.component.html (list with links)">
</code-example>
You'll have to fix the private stylesheet (`heroes.component.css`) to make
@ -637,7 +612,6 @@ Here's the class after pruning away the dead code.
path="toh-pt5/src/app/heroes/heroes.component.ts"
region="class"
title="src/app/heroes/heroes.component.ts (cleaned up)" linenums="false">
</code-example>
## Routable *HeroDetailComponent*
@ -679,7 +653,6 @@ Add the following imports:
path="toh-pt5/src/app/hero-detail/hero-detail.component.ts"
region="added-imports"
title="src/app/hero-detail/hero-detail.component.ts">
</code-example>
{@a hero-detail-ctor}
@ -691,7 +664,6 @@ into the constructor, saving their values in private fields:
<code-example
path="toh-pt5/src/app/hero-detail/hero-detail.component.ts" region="ctor">
</code-example>
The [`ActivatedRoute`](api/router/ActivatedRoute) holds information about the route to this instance of the `HeroDetailComponent`.
@ -725,7 +697,6 @@ call `getHero()` and define it as follows.
<code-example
path="toh-pt5/src/app/hero-detail/hero-detail.component.ts" region="ngOnInit">
</code-example>
The `route.snapshot` is a static image of the route information shortly after the component was created.
@ -764,7 +735,6 @@ Open `HeroService` and add this `getHero()` method
path="toh-pt5/src/app/hero.service.ts"
region="getHero"
title="src/app/hero.service.ts (getHero)">
</code-example>
<div class="alert is-important">
@ -829,7 +799,6 @@ to the component's `goBack()` method.
path="toh-pt5/src/app/hero-detail/hero-detail.component.html"
region="back-button"
title="src/app/hero-detail/hero-detail.component.html (back button)">
</code-example>
Add a `goBack()` _method_ to the component class that navigates backward one step
@ -870,7 +839,6 @@ Here are the code files discussed on this page and your app should look like thi
#### `AppRoutingModule`、`AppModule` 和 `HeroService`
<code-tabs>
<code-pane
title="src/app/app-routing.module.ts"
path="toh-pt5/src/app/app-routing.module.ts">
@ -883,7 +851,6 @@ Here are the code files discussed on this page and your app should look like thi
title="src/app/hero.service.ts"
path="toh-pt5/src/app/hero.service.ts">
</code-pane>
</code-tabs>
{@a appcomponent}
@ -891,7 +858,6 @@ Here are the code files discussed on this page and your app should look like thi
#### _AppComponent_
<code-tabs>
<code-pane
title="src/app/app.component.html"
path="toh-pt5/src/app/app.component.html">
@ -901,7 +867,6 @@ Here are the code files discussed on this page and your app should look like thi
title="src/app/app.component.css"
path="toh-pt5/src/app/app.component.css">
</code-pane>
</code-tabs>
{@a dashboardcomponent}
@ -909,7 +874,6 @@ Here are the code files discussed on this page and your app should look like thi
#### _DashboardComponent_
<code-tabs>
<code-pane
title="src/app/dashboard/dashboard.component.html" path="toh-pt5/src/app/dashboard/dashboard.component.html">
</code-pane>
@ -921,7 +885,6 @@ Here are the code files discussed on this page and your app should look like thi
<code-pane
title="src/app/dashboard/dashboard.component.css" path="toh-pt5/src/app/dashboard/dashboard.component.css">
</code-pane>
</code-tabs>
{@a heroescomponent}
@ -929,7 +892,6 @@ Here are the code files discussed on this page and your app should look like thi
#### _HeroesComponent_
<code-tabs>
<code-pane
title="src/app/heroes/heroes.component.html" path="toh-pt5/src/app/heroes/heroes.component.html">
</code-pane>
@ -943,7 +905,6 @@ Here are the code files discussed on this page and your app should look like thi
title="src/app/heroes/heroes.component.css"
path="toh-pt5/src/app/heroes/heroes.component.css">
</code-pane>
</code-tabs>
{@a herodetailcomponent}
@ -951,7 +912,6 @@ Here are the code files discussed on this page and your app should look like thi
#### _HeroDetailComponent_
<code-tabs>
<code-pane
title="src/app/hero-detail/hero-detail.component.html" path="toh-pt5/src/app/hero-detail/hero-detail.component.html">
</code-pane>
@ -963,7 +923,6 @@ Here are the code files discussed on this page and your app should look like thi
<code-pane
title="src/app/hero-detail/hero-detail.component.css" path="toh-pt5/src/app/hero-detail/hero-detail.component.css">
</code-pane>
</code-tabs>
## Summary

View File

@ -89,9 +89,7 @@ Install the *In-memory Web API* package from _npm_
`npm` 中安装这个*内存 Web API* 包(译注:请使用 0.5+ 的版本,不要使用 0.4-
<code-example language="sh" class="code-shell">
npm install angular-in-memory-web-api --save
</code-example>
Import the `InMemoryWebApiModule` and the `InMemoryDataService` class,
@ -103,7 +101,6 @@ which you will create in a moment.
path="toh-pt6/src/app/app.module.ts"
region="import-in-mem-stuff"
title="src/app/app.module.ts (In-memory Web API imports)">
</code-example>
Add the `InMemoryWebApiModule` to the `@NgModule.imports` array&mdash;
@ -116,7 +113,6 @@ _after importing the `HttpClient`_,
<code-example
path="toh-pt6/src/app/app.module.ts"
region="in-mem-web-api-imports">
</code-example>
The `forRoot()` configuration method takes an `InMemoryDataService` class
@ -157,7 +153,6 @@ Import some HTTP symbols that you'll need:
path="toh-pt6/src/app/hero.service.ts"
region="import-httpclient"
title="src/app/hero.service.ts (import HTTP symbols)">
</code-example>
Inject `HttpClient` into the constructor in a private property called `http`.
@ -167,7 +162,6 @@ Inject `HttpClient` into the constructor in a private property called `http`.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="ctor" >
</code-example>
Keep injecting the `MessageService`. You'll call it so frequently that
@ -178,7 +172,6 @@ you'll wrap it in private `log` method.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="log" >
</code-example>
Define the `heroesUrl` with the address of the heroes resource on the server.
@ -188,7 +181,6 @@ Define the `heroesUrl` with the address of the heroes resource on the server.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="heroesUrl" >
</code-example>
### Get heroes with _HttpClient_
@ -205,7 +197,6 @@ as an `Observable<Hero[]>`.
path="toh-pt4/src/app/hero.service.ts"
region="getHeroes-1"
title="src/app/hero.service.ts (getHeroes with RxJs 'of()')">
</code-example>
Convert that method to use `HttpClient`
@ -215,7 +206,6 @@ Convert that method to use `HttpClient`
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="getHeroes-1">
</code-example>
Refresh the browser. The hero data should successfully load from the
@ -304,7 +294,6 @@ Import the `catchError` symbol from `rxjs/operators`, along with some other oper
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="import-rxjs-operators">
</code-example>
Now extend the observable result with the `.pipe()` method and
@ -315,7 +304,6 @@ give it a `catchError()` operator.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="getHeroes-2" >
</code-example>
The `catchError()` operator intercepts an **`Observable` that failed**.
@ -344,7 +332,6 @@ has configured with both the name of the operation that failed and a safe return
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="handleError">
</code-example>
After reporting the error to console, the handler constructs
@ -381,7 +368,6 @@ Here is the final version of `getHeroes` with the `tap` that logs the operation.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="getHeroes" >
</code-example>
### Get hero by id
@ -459,7 +445,6 @@ on the server.
path="toh-pt6/src/app/hero.service.ts"
region="updateHero"
title="src/app/hero.service.ts (update)">
</code-example>
The `HttpClient.put()` method takes three parameters
@ -491,7 +476,6 @@ That header is in the `httpOptions` constant defined in the `HeroService`.
<code-example
path="toh-pt6/src/app/hero.service.ts"
region="http-options">
</code-example>
Refresh the browser, change a hero name, save your change,
@ -690,7 +674,6 @@ Start by adding a `searchHeroes` method to the `HeroService`.
path="toh-pt6/src/app/hero.service.ts"
region="searchHeroes"
title="src/app/hero.service.ts">
</code-example>
The method returns immediately with an empty array if there is no search term.
@ -713,7 +696,6 @@ Add the hero search element, `<app-hero-search>`, to the bottom of the `Dashboar
<code-example
path="toh-pt6/src/app/dashboard/dashboard.component.html" title="src/app/dashboard/dashboard.component.html" linenums="false">
</code-example>
This template looks a lot like the `*ngFor` repeater in the `HeroesComponent` template.
@ -739,9 +721,7 @@ Create a `HeroSearchComponent` with the CLI.
使用 CLI 创建一个 `HeroSearchComponent`
<code-example language="sh" class="code-shell">
ng generate component hero-search
</code-example>
The CLI generates the three `HeroSearchComponent` and adds the component to the `AppModule' declarations
@ -811,7 +791,6 @@ Notice the declaration of `heroes$` as an `Observable`
<code-example
path="toh-pt6/src/app/hero-search/hero-search.component.ts"
region="heroes-stream">
</code-example>
You'll set it in [`ngOnInit()`](#search-pipe).
@ -876,7 +855,6 @@ Here's the code.
<code-example
path="toh-pt6/src/app/hero-search/hero-search.component.ts"
region="search">
</code-example>
* `debounceTime(300)` waits until the flow of new string events pauses for 300 milliseconds
@ -960,7 +938,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
#### _HeroService_, _InMemoryDataService_, _AppModule_
<code-tabs>
<code-pane
title="hero.service.ts"
path="toh-pt6/src/app/hero.service.ts">
@ -973,7 +950,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
title="app.module.ts"
path="toh-pt6/src/app/app.module.ts">
</code-pane>
</code-tabs>
{@a heroescomponent}
@ -981,7 +957,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
#### _HeroesComponent_
<code-tabs>
<code-pane
title="heroes/heroes.component.html"
path="toh-pt6/src/app/heroes/heroes.component.html">
@ -994,7 +969,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
title="heroes/heroes.component.css"
path="toh-pt6/src/app/heroes/heroes.component.css">
</code-pane>
</code-tabs>
{@a herodetailcomponent}
@ -1002,7 +976,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
#### _HeroDetailComponent_
<code-tabs>
<code-pane
title="hero-detail/hero-detail.component.html"
path="toh-pt6/src/app/hero-detail/hero-detail.component.html">
@ -1011,7 +984,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
title="hero-detail/hero-detail.component.ts"
path="toh-pt6/src/app/hero-detail/hero-detail.component.ts">
</code-pane>
</code-tabs>
{@a herosearchcomponent}
@ -1019,7 +991,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
#### _HeroSearchComponent_
<code-tabs>
<code-pane
title="hero-search/hero-search.component.html"
path="toh-pt6/src/app/hero-search/hero-search.component.html">
@ -1032,7 +1003,6 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
title="hero-search/hero-search.component.css"
path="toh-pt6/src/app/hero-search/hero-search.component.css">
</code-pane>
</code-tabs>
## Summary

View File

@ -3,5 +3,5 @@
import { dirs } from '../dirs';
import { translateFile } from '../translate';
const filename = 'guide/testing.md';
const filename = 'guide/aot-compiler.md';
translateFile(__dirname + '/../../../../../content-en/' + filename, dirs.content + filename);

View File

@ -2,4 +2,5 @@ export class DictEntry {
original: string;
translation: string;
sourceFile?: string;
key: string;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
import * as globby from 'globby';
import { DictEntry } from './dict-entry';
import {
extractOriginalContent,
isNotCnPages,
isOnlyBeginTag,
isOnlyBeginTag, hasInlineText, kernelText,
normalizeLines,
originalIsNotChinese,
originalIsNotCodeExampleTag,
@ -29,7 +30,14 @@ export function gatherTranslations(text: string): DictEntry[] {
const result = [];
for (let i = 1; i < lines.length; ++i) {
const translation = purifyText(lines[i]);
if (isTranslation(translation)) {
if (hasInlineText(translation)) {
const originalContent = extractOriginalContent(translation);
result.push({
key: kernelText(originalContent),
original: originalContent,
translation
});
} else if (isTranslation(translation)) {
const original = purifyText(lines[i - 1]);
// 对于包裹在 html tag 中的翻译文本进行特殊处理
if (isOnlyBeginTag(original)) {
@ -38,18 +46,18 @@ export function gatherTranslations(text: string): DictEntry[] {
const thisEndTag = lines[i + 1].trim();
if (original === prevBeginTag && prevEndTag === thisEndTag) {
result.push({
key: kernelText(lines[i - 3]),
original: lines[i - 3],
translation: lines[i],
});
}
} else {
result.push({original, translation});
result.push({key: kernelText(original), original, translation});
}
}
}
return result
.filter(isNotCnPages)
.filter(translationHasNotCodeExample)
.filter(originalIsNotChinese)
.filter(originalIsNotSpecialDivTag)
.filter(originalIsNotCodeExampleTag)
@ -84,6 +92,7 @@ export function purifyText(text): string {
export function purifyEntry(entry: DictEntry): DictEntry {
return {
key: entry.key,
original: purifyText(entry.original),
translation: purifyText(entry.translation),
};

View File

@ -1,17 +1,13 @@
import { expect } from 'chai';
import { lookup } from './translate';
import { kernelText } from './utils';
import { lookup, translate } from './translate';
describe('根据字典进行翻译', () => {
it('抽取核心字符', function () {
expect(kernelText(' # Forms ABC. ')).eql('#FormsABC');
});
it('查字典', () => {
expect(lookup('# Forms')[0].translation).eql('# 表单');
});
it('对包裹在 a 标签中的内容查字典', () => {
it('翻译 header', () => {
expect(translate(`<header></header>`)).eql(``);
});
});

View File

@ -3,28 +3,37 @@ import * as _ from 'lodash';
import { DictEntry } from './dict-entry';
import { dirs } from './dirs';
import { listMarkdownFiles } from './extractor';
import { exactlyTest, indentOf, normalizeLines, repeat } from './utils';
import { exactlyTest, extractOriginalContent, indentOf, hasInlineText, kernelText, normalizeLines, repeat } from './utils';
// TODO: 改用 markdown 解析器实现
export const dict = require('./dict-latest.json') as DictEntry[];
export function lookup(english: string, filename: RegExp = /.*/): DictEntry[] {
export function lookup(english: string): DictEntry[] {
const englishKernel = kernelText(extractOriginalContent(english));
const entries = dict
.filter(entry => filename.test(entry.sourceFile))
.filter(entry => exactlyTest(entry.original, english));
.filter(entry => exactlyTest(entry.key, englishKernel));
return _.uniqBy(entries, 'translation');
}
function isPureTag(line: string): boolean {
let content = line.trim();
return /^<\/?\w+\b[^>]*>$/.test(content) ||
/^<(\w+)\b[^>]*>\s*<\/\1>$/.test(content);
}
export function translate(content: string): string[] {
const lines = normalizeLines(content)
.split(/\n+\s*\n+/);
.split(/\n{2,}/);
return lines
.map(line => {
if (!line.trim()) {
if (!line.trim() || isPureTag(line)) {
return line;
}
const translations = lookup(line);
if (translations.length > 0 && hasInlineText(translations[0].translation)) {
return translations[0].translation;
} else {
const indent = indentOf(line);
const padding = repeat(indent);
if (translations.length === 0) {
@ -34,13 +43,14 @@ export function translate(content: string): string[] {
} else {
return line + '\n\n' + padding + translations[translations.length - 1].translation;
}
}
});
}
export function translateFile(sourceFile: string, targetFile: string): void {
const content = fs.readFileSync(sourceFile, 'utf-8');
const result = translate(content);
fs.writeFileSync(targetFile, result.join('\n\n').trim() + '\n', 'utf-8');
fs.writeFileSync(targetFile, result.join('\n\n') + '\n', 'utf-8');
}
export function translateDirectory(sourceDir: string, targetDir: string): void {

View File

@ -1,48 +1,40 @@
import { expect } from 'chai';
import { fuzzyTest, normalizeLines, tokenize } from './utils';
import { fuzzyTest, hasInlineText, kernelText, normalizeLines, tokenize } from './utils';
describe(' 工具函数', () => {
it('把“1. ”列表处理成空行分隔的格式,以便处理', function () {
const lines = normalizeLines(`1. abc
11. def
`);
expect(lines).eql(`
1. abc
expect(lines).eql(`1. abc
11. def
`);
11. def`);
});
it('把“- ”列表处理成空行分隔的格式,以便处理', function () {
const lines = normalizeLines(`- abc
- def
`);
expect(lines).eql(`
- abc
expect(lines).eql(`- abc
- def
`);
- def`);
});
it('把“* ”列表处理成空行分隔的格式,以便处理', function () {
const lines = normalizeLines(`* abc
* def
`);
expect(lines).eql(`
* abc
expect(lines).eql(`* abc
* def
`);
* def`);
});
it('把“# ”标题处理成空行分隔的格式,以便处理', function () {
const lines = normalizeLines(`\n# abc
def`);
expect(lines).eql(`
# abc
expect(lines).eql(`# abc
def
`);
def`);
});
it('拆解单行的成对 tag', function () {
@ -51,13 +43,11 @@ def
<div class="abc">DEF</div>
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<div class="abc">DEF</div>
b
`);
b`);
});
it('拆解单行的自封闭 tag', function () {
@ -66,13 +56,11 @@ def
<hr/>
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<hr/>
b
`);
b`);
});
it('拆解单行的 h\\d 标签', function () {
const lines = normalizeLines(`
@ -80,13 +68,11 @@ def
<h3 id="abc">line</h3>
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<h3 id="abc">line</h3>
b
`);
b`);
});
it('把多行 hn 处理成单行', function () {
@ -95,9 +81,7 @@ def
abc
</h3>
`);
expect(lines).eql(`
<h3 id="nav">abc</h3>
`);
expect(lines).eql(`<h3 id="nav">abc</h3>`);
});
it('拆解单行的 th 标签', function () {
@ -106,8 +90,7 @@ def
<th>line</th>
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<th>
@ -115,8 +98,7 @@ def
</th>
b
`);
b`);
});
it('拆解单行注释', function () {
@ -125,13 +107,11 @@ def
<!-- no -->
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<!-- no -->
b
`);
b`);
});
it('拆解多行注释', function () {
@ -141,14 +121,12 @@ def
abc -->
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<!-- no
abc -->
b
`);
b`);
});
it('拆解单行br', function () {
@ -157,41 +135,83 @@ def
<br class="clear">
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
<br class="clear">
b
`);
b`);
});
it('拆解 code-example', function () {
const lines = normalizeLines(`
<code-example language="sh" class="code-shell">
abc
<code-example
language="sh" class="code-shell">
ng generate directive highlight
</code-example>
def
`);
expect(lines).eql(`
<code-example language="sh" class="code-shell">
expect(lines).eql(`abc
<code-example
language="sh" class="code-shell">
ng generate directive highlight
`);
</code-example>
def`);
});
it('不拆解引用的 code-example', function () {
const lines = normalizeLines(`
abc
> <code-example > abc </code-example>
def
`);
expect(lines).eql(`abc
> <code-example > abc </code-example>
def`);
});
it('为单行的 li 和 ul 前后添加空行', function () {
const lines = normalizeLines(`
a
<li>
b
</li>
c
<ul>
</ul>
`);
expect(normalizeLines(lines)).eql(`a
<li>
b
</li>
c
<ul>
</ul>`);
});
it('拆解 @a 标记', function () {
const lines = normalizeLines(`
a
{@a test}
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
{@a test}
b
`);
b`);
});
it('拆解多行代码', function () {
@ -202,8 +222,7 @@ ng generate directive highlight
\`\`\`
b
`);
expect(lines).eql(`
a
expect(lines).eql(`a
\`\`\`
@ -211,43 +230,29 @@ ng generate directive highlight
\`\`\`
b
`);
b`);
});
it('拆解多行的成对 tag', function () {
it('把多行的 p 元素合并成单行', function () {
const lines = normalizeLines(`
<p>
a
</p>
<p>
</p>
`);
expect(lines).eq(`
<p>
expect(lines).eq(`<p>a</p>
a
</p>
<p>
</p>
`);
<p></p>`);
});
it('不要拆解 header', function () {
const lines = normalizeLines(`
<header>Angular forms don't require a style library</header>
`);
expect(lines).eq(`
<header>Angular forms don't require a style library</header>
`);
expect(lines).eq(`<header>Angular forms don't require a style library</header>`);
});
it('拆解独行的 th/td', function () {
@ -255,20 +260,29 @@ ng generate directive highlight
<td>
abc
</td>
`)).eql(`
<td>
`)).eql(`<td>
abc
</td>
`);
</td>`);
});
it('拆解 pre', function () {
expect(normalizeLines(`
ABC
<pre>def</pre>
ghi
`)).eql(`ABC
<pre>def</pre>
ghi`);
});
it('拆解任意位置的 <tr>', function () {
expect(normalizeLines(`
<tr><td>abc</td></tr>
`)).eql(`
<tr>
`)).eql(`<tr>
<td>
@ -276,8 +290,7 @@ ng generate directive highlight
</td>
</tr>
`);
</tr>`);
});
it('拆解独行的 li', function () {
expect(normalizeLines(`
@ -287,8 +300,7 @@ ng generate directive highlight
<li><a href="#">c</a></li>
</ul>
`)).eql(`
<ul>
`)).eql(`<ul>
<li>
@ -308,16 +320,13 @@ ng generate directive highlight
</li>
</ul>
`);
</ul>`);
});
it('不要拆解行内的 html tag', function () {
expect(normalizeLines(`
a <b> c
`)).eql(`
a <b> c
`);
`)).eql(`a <b> c`);
});
it('把连续的三行及以上空行简化为两个空行', function () {
const lines = normalizeLines(`
@ -325,17 +334,23 @@ a <b> c
b`);
expect(lines).eql(`
a
expect(lines).eql(`a
b
`);
b`);
});
it('拆分', function () {
expect(tokenize('abc def,abc.')).eql(['abc', 'def', 'abc']);
});
it('抽取核心字符', function () {
expect(kernelText(' # Forms ABC. ')).eql('#FORMSABC');
});
it('删除非核心字符', function () {
expect(kernelText('Abc-132-@#!abc')).eql('ABC132#ABC');
});
it('模糊匹配', function () {
expect(fuzzyTest(`a b c d e`, `a b c d e`)).is.false;
expect(fuzzyTest(`a b c d e f g`, `a b c d e`)).is.false;
@ -344,4 +359,12 @@ a <b> c
in a helper such as the \`click()\` function below:
`)).is.true;
});
it('检测是否表格', function () {
expect(hasInlineText(`
abc | def
----|---
gh | ij
`)).eql(true);
});
});

View File

@ -51,51 +51,87 @@ export function isHead(line: string): boolean {
}
export function normalizeLines(text: string): string {
text = '\n' + text + '\n';
// 为列表、标题等自带换行含义的markdown多加一个空行
const blockElementPattern = /(?=\n *(\d+\.|-|\*) )\n/g;
text = text.replace(blockElementPattern, '\n\n');
const hxPattern = /(\n *#+ .*)(?=\n)/g;
text = text.replace(hxPattern, '\n$1\n');
const hxMultilinePattern = /(\n *)<(h\d+)([^>\n]*)>\n+ *(.*)\n+ *(<\/\2>)(?=\n)/g;
text = text.replace(hxMultilinePattern, '\n$1<$2$3>$4</$2>\n');
const oneLinePairedTagPattern = /\n( *)<(p|div|h\d+|code-example|section)( ?[^>\n]*)>([^<\n]*)<\/\2>( *)(?=\n)/g;
text = text.replace(oneLinePairedTagPattern, '\n\n$1<$2$3>$4</$2>$5\n');
const oneLineThTdTagPattern = /\n( *)(?!`)<(th|td|li)( ?[^>\n]*)>(?!`)(.*)<\/\2>( *)(?=\n)/g;
text = text.replace(oneLineThTdTagPattern, '\n\n$1<$2$3>\n\n$1 $4\n\n$1</$2>$5\n');
const oneLineCommentPattern = /\n( *)(<!--[\s\S]*?-->)( *)(?=\n)/g;
text = text.replace(oneLineCommentPattern, '\n\n$1$2$3\n');
const oneLineBrTagPattern = /\n( *)(<br class="clear">)( *)(?=\n)/g;
text = text.replace(oneLineBrTagPattern, '\n\n$1$2$3\n');
// 原文中有 back to top 被分成两行的情况,这里把它标准化一下
const specialBackToTopPattern = /<a href="#toc">Back to top\s+<\/a>/g;
text = text.replace(specialBackToTopPattern, '<a href="#toc">Back to top</a>');
// 原文中有</table为它补齐
text = text.replace(/^ *<\/table$/gm, '</table>');
// 原文中有的换行会干扰生成 html 的格式,替换一下
// tslint:disable:max-line-length
text = text.replace(`<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">
Get them now</a> if they're not already installed on your machine.
`, `<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">Get them now</a> if they're not already installed on your machine.
`);
const backToTopPattern = /\n( *)(<a href="#toc">Back to top<\/a>)( *)(?=\n)/g;
text = text.replace(backToTopPattern, '\n\n$1$2$3\n');
const atTagCommentPattern = /\n( *)({@a.*})( *)(?=\n)/g;
text = text.replace(atTagCommentPattern, '\n\n$1$2$3\n');
const oneLineClosedTagPattern = /\n( *)<(hr)(\/?)>( *)(?=\n)/g;
text = text.replace(oneLineClosedTagPattern, '\n\n$1<$2$3>$4\n');
// 为各种列表多加一个空行
const listElementPattern = /(?=\n *(\d+\.|-|\*) )\n/g;
text = text.replace(listElementPattern, '\n\n');
// 为标题增加空行
const hxPattern = /^( *#+ .*)$/gm;
text = text.replace(hxPattern, '\n$1\n');
// 把多行的 HTML 标题或 p 元素变成单行
const hxMultilinePattern = /^( *)<(h\d|p|header)([^>]*)>\s*(.*)\s*<\/\2>$/gm;
text = text.replace(hxMultilinePattern, '\n$1<$2$3>$4</$2>\n');
// 为单行的成对标签前后添加空行
const oneLinePairedTagPattern = /^( *)<(p|div|h\d+|code-example|section)\b([^>]*)>([^\n]*?)<\/\2>( *)$/gm;
text = text.replace(oneLinePairedTagPattern, '\n$1<$2$3>$4</$2>$5\n');
// 为单行的注释前后添加空行
const oneLineCommentPattern = /^( *<!--[\s\S]*?--> *)$/gm;
text = text.replace(oneLineCommentPattern, '\n$1\n');
// 为单行的 back to top 前后添加空行
const backToTopPattern = /^( *<a href="#toc">Back to top<\/a> *)$/gm;
text = text.replace(backToTopPattern, '\n$1\n');
// 为单行的 {@ 语句前后添加空行
const atTagCommentPattern = /^( *{@a.*} *)$/gm;
text = text.replace(atTagCommentPattern, '\n$1\n');
// 为单行的自封闭标签前后添加空行
const oneLineClosedTagPattern = /^( *<hr *\/?>) *$/gm;
text = text.replace(oneLineClosedTagPattern, '\n$1\n');
// 为单行的 <br class="clear"> 前后添加空行
const oneLineBrTagPattern = /^( *<br class="clear"> *)$/gm;
text = text.replace(oneLineBrTagPattern, '\n$1\n');
// 为单独的 div 前后添加空行
const oneLineDivTagPattern = /^( *<\/?(div|li|ul|ol)\b([^>]*)> *)$/gm;
text = text.replace(oneLineDivTagPattern, '\n$1\n');
// 在 pre 前后添加空行
const preBeginTagPattern = /(^ *<pre)/gm;
text = text.replace(preBeginTagPattern, '\n$1');
const preEndTagPattern = /(<\/pre> *)$/gm;
text = text.replace(preEndTagPattern, '$1\n');
const trTagPattern = /( *)(<tr\b *[^>\n]*>)(.*)(<\/tr>)/g;
text = text.replace(trTagPattern, '\n\n$1$2\n\n$1 $3\n\n$1$4\n\n');
// 为 ``` 前后添加空行
const multiLineCodePattern = /^( *```\w* *)$/gm;
text = text.replace(multiLineCodePattern, '\n$1\n');
const thTdTagPattern = /( *)(?!`)<(th|td)\b( *[^>\n]*)>(?!`)([\s\S]*?)<\/\2>/g;
// 把单行的 tr 拆成多行,以便翻译
const trTagPattern = /^( *)(<tr\b[^>]*>)(.*)(<\/tr>)$/gm;
text = text.replace(trTagPattern, '\n$1$2\n\n$1 $3\n\n$1$4\n');
// 把单行的 th/td/li 等拆成多行,以便翻译,
const oneLineThTdTagPattern = /^( *)<(th|td|li)\b([^>]*)>(.*?)<\/\2>$/gm;
text = text.replace(oneLineThTdTagPattern, '\n$1<$2$3>\n\n$1 $4\n\n$1</$2>\n');
// 把原本就是多行的 th/td 中间添加空行
const thTdTagPattern = /^( *)<(th|td)\b( *[^>]*)>([\s\S]*?)<\/\2>$/gm;
text = text.replace(thTdTagPattern, '\n\n$1<$2$3>\n\n$1 $4\n\n$1</$2>\n\n');
const blockTagPattern = /\n( *)(?!`)<(\/?)(td|th|div|code-example|code-tabs|h\d+|p|tr)\b( *[^>\n]*)>(?!`)( *)(?=\n)/g;
text = text.replace(blockTagPattern, '\n\n$1<$2$3$4>$5\n');
// 在所有的起始标签前面加空行
const blockBeginTagPattern = /^( *)<(code-example|code-tabs|pre|p)\b( *[^>]*)>( *)$/gm;
text = text.replace(blockBeginTagPattern, '\n$1<$2$3>$4');
const multiLineCodePattern = /\n( *)```(\w*)( *)(?=\n)/g;
text = text.replace(multiLineCodePattern, '\n\n$1```$2$3\n');
// 在所有的结束标签前面加空行
const blockEndTagPattern = /^( *)<\/(code-example|code-tabs|pre|p)>( *)$/gm;
text = text.replace(blockEndTagPattern, '$1</$2>$3\n');
const multipleBlankLinePattern = /\n\s*\n+/g;
// 把所有由空格组成的空行都去掉
const blankLinePattern = /^[ \t]+$/gm;
text = text.replace(blankLinePattern, '');
// 把中间的多个回车都变成两个回车
const multipleBlankLinePattern = /\n{2,}/g;
text = text.replace(multipleBlankLinePattern, '\n\n');
text = text.replace(/^\n+/, '\n').replace(/\n+$/, '\n');
// 去掉全文头尾的空白
text = text.trim();
return text;
}
@ -129,14 +165,13 @@ export function fuzzyTest(text1: string, text2: string): boolean {
return sameTokens.length > 5 && sameTokens.length / maxTokens >= 0.8;
}
export function exactlyTest(text1: string, text2: string): boolean {
return kernelText(text1) === kernelText(text2);
export function exactlyTest(key: string, text: string): boolean {
return key && key === text;
}
export function kernelText(text: string): string {
return text
.replace(/[\s\n]+/g, '')
.replace(/\.$/g, '')
.replace(/([^a-zA-Z0-9#:]|\s|\.$)/g, '')
.toUpperCase()
.trim();
}
@ -146,3 +181,15 @@ export function tokenize(text: string): string[] {
.map(token => token.trim())
.filter(token => !!token);
}
export function hasInlineText(text: string): boolean {
return /<t>(.*?)<\/t> *<t>.*?<\/t>/g.test(text);
}
export function extractOriginalContent(text: string): string {
if (!hasInlineText(text)) {
return text;
}
return text.replace(/<t>(.*?)<\/t> *<t>.*?<\/t>/gi, '$1')
.replace(/ +/g, ' ');
}