fix: 修订完了 guide 部分
This commit is contained in:
parent
4ac2511634
commit
df222c3a12
@ -626,7 +626,7 @@ The following format message in the component template binds to the component's
|
||||
which outputs one of the following string values: "male", "female" or "other".
|
||||
The message maps those values to the appropriate translations:
|
||||
|
||||
组件模板中的下列消息格式绑定到了组件的 `gender` 属性,这个属性的取值是 "m" 或 "f" 或 "o"。
|
||||
组件模板中的下列消息格式绑定到了组件的 `gender` 属性,这个属性的取值是 "male"、"female" 或 "other"。
|
||||
这个消息会把那些值映射到适当的翻译文本:
|
||||
|
||||
<code-example path="i18n/src/app/app.component.html" region="i18n-select" header="src/app/app.component.html" linenums="false">
|
||||
|
@ -299,7 +299,7 @@ Now, if you view the app in the browser, the three buttons take you to each modu
|
||||
You can check to see that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the dev tools by pressing `Cmd+Option+i` on a Mac or `Ctrl+Shift+j` on a PC and go to the Network Tab.
|
||||
|
||||
你可以使用 Chrome 开发者工具来确认一下这些模块真的是惰性加载的。
|
||||
在 Chrome 中,按 `Cmd+Option+i`(Mac)或 `Ctrl+Alt+i`(PC),并选中 `Network` 页标签。
|
||||
在 Chrome 中,按 `Cmd+Option+i`(Mac)或 `Ctrl+Shift+j`(PC),并选中 `Network` 页标签。
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
|
||||
|
@ -357,9 +357,9 @@ Only call and import a `forRoot()` result in the root application module, `AppMo
|
||||
Avoid importing it in any other module, particularly in a lazy-loaded module. For more
|
||||
information on `forRoot()` see [the `forRoot()` pattern](guide/singleton-services#the-forroot-pattern) section of the [Singleton Services](guide/singleton-services) guide.
|
||||
|
||||
只能在应用的根模块 `AppModule` 中调用并导入 `.forRoot()` 的结果。
|
||||
在其它模块中导入它,特别是惰性加载模块中,是违反设计目标的并会导致一个运行时错误。
|
||||
要了解更多,参见[单例服务](guide/singleton-services)。
|
||||
只能在应用的根模块 `AppModule` 中调用并导入 `forRoot()` 的结果。
|
||||
在其它模块,特别是惰性加载模块中,不要导入它。
|
||||
要了解关于 `forRoot()` 的更多信息,参见[单例服务](guide/singleton-services)一章的 [the `forRoot()` 模式](guide/singleton-services#the-forroot-pattern)部分。
|
||||
|
||||
For a service, instead of using `forRoot()`, specify `providedIn: 'root'` on the service's `@Injectable()` decorator, which
|
||||
makes the service automatically available to the whole application and thus singleton by default.
|
||||
@ -368,7 +368,7 @@ makes the service automatically available to the whole application and thus sing
|
||||
|
||||
`RouterModule` also offers a `forChild()` static method for configuring the routes of lazy-loaded modules.
|
||||
|
||||
`RouterModule` 也提供了静态方法 `forChild`,用于配置惰性加载模块的路由。
|
||||
`RouterModule` 也提供了静态方法 `forChild()`,用于配置惰性加载模块的路由。
|
||||
|
||||
`forRoot()` and `forChild()` are conventional names for methods that
|
||||
configure services in root and feature modules respectively.
|
||||
|
@ -156,7 +156,7 @@ The [Browser Support](guide/browser-support) guide explains which browsers need
|
||||
how you can add them.
|
||||
|
||||
很多浏览器欠缺对 Angular 所需的某些最新 HTML 标准、特性的原生支持。
|
||||
[腻子脚本](https://en.wikipedia.org/wiki/Polyfill) 可以模拟这些缺失的特性。
|
||||
[腻子脚本](https://en.wikipedia.org/wiki/Polyfill_(programming) 可以模拟这些缺失的特性。
|
||||
[浏览器支持](guide/browser-support)一章中解释了哪些浏览器分别需要哪些腻子脚本,以及如何添加它们。
|
||||
|
||||
The `package.json` for a new Angular workspace installs the [core-js](https://github.com/zloirock/core-js) package,
|
||||
|
@ -52,7 +52,7 @@ You can now inject `UserService` anywhere in your application.
|
||||
|
||||
The service itself is a class that the CLI generated and that's decorated with `@Injectable()`. By default, this decorator has a `providedIn` property, which creates a provider for the service. In this case, `providedIn: 'root'` specifies that Angular should provide the service in the root injector.
|
||||
|
||||
该服务本身是 CLI 创建的一个类,并且加上了 `@Injectable` 装饰器。默认情况下,该装饰器是用 `providedIn` 属性进行配置的,它会为该服务创建一个提供商。在这个例子中,`providedIn: 'root'` 指定该服务应该在根注入器中提供。
|
||||
该服务本身是 CLI 创建的一个类,并且加上了 `@Injectable()` 装饰器。默认情况下,该装饰器是用 `providedIn` 属性进行配置的,它会为该服务创建一个提供商。在这个例子中,`providedIn: 'root'` 指定 Angular 应该在根注入器中提供该服务。
|
||||
|
||||
## Provider scope
|
||||
|
||||
|
@ -364,7 +364,7 @@ After you update the model in the component class, update the template to connec
|
||||
|
||||
Add the `address` form group containing the `street`, `city`, `state`, and `zip` fields to the `ProfileEditor` template.
|
||||
|
||||
把包含 `firstName` 和 `lastName` 字段的 `address` 表单组添加到 `ProfileEditor` 模板中。
|
||||
把包含 `street`、`city`、`state` 和 `zip` 字段的 `address` 表单组添加到 `ProfileEditor` 模板中。
|
||||
|
||||
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.1.html" region="formgroupname" linenums="false" header="src/app/profile-editor/profile-editor.component.html (template nested form group)">
|
||||
|
||||
|
@ -33,7 +33,7 @@ Angular 的版本号表明本次发布中所引入的变更级别。它使用[
|
||||
|
||||
Angular version numbers have three parts: `major.minor.patch`. For example, version 7.2.11 indicates major version 7, minor version 2, and patch level 11.
|
||||
|
||||
Angular 的版本号包括三个部分:`major.minor.patch`。比如,版本 5.2.9 表示主版本号是 5,小版本号是 2,补丁版本号是 9。
|
||||
Angular 的版本号包括三个部分:`major.minor.patch`。比如,版本 7.2.11 表示主版本号是 7,小版本号是 2,补丁版本号是 11。
|
||||
|
||||
The version number is incremented based on the level of change included in the release.
|
||||
|
||||
@ -41,27 +41,32 @@ The version number is incremented based on the level of change included in the r
|
||||
|
||||
* **Major releases** contain significant new features, some but minimal developer assistance is expected during the update. When updating to a new major release, you may need to run update scripts, refactor code, run additional tests, and learn new APIs.
|
||||
|
||||
**主版本**包含重要的新特性,其中的部分特性在升级时会需要由开发人员提供少量的协助才能完成。当升级到新的主版本时,你可能需要运行升级脚本、重构代码、运行其它测试以及学习新的 API。
|
||||
|
||||
* **Minor releases** contain new smaller features. Minor releases are fully backward-compatible; no developer assistance is expected during update, but you can optionally modify your apps and libraries to begin using new APIs, features, and capabilities that were added in the release. We update peer dependencies in minor versions by expanding the supported versions, but we do not require projects to update these dependencies.
|
||||
|
||||
**小版本**包含新的小型特性。小版本是完全向后兼容的,在升级期间,不需要开发人员提供协助,但是你可以(可选的)修改你的应用和库,来使用本次发布中新增的 API、特性和能力。我们会扩展库的对等依赖(peer dependency)中的小版本号范围来更新库同级,但并不需要你的项目也更新那些依赖。
|
||||
|
||||
* **Patch releases** are low risk, bug fix releases. No developer assistance is expected during update.
|
||||
|
||||
**补丁版本**是风险最低的、修 BUG 的版本。在升级期间完全不需要开发人员的协助。
|
||||
|
||||
{@a updating}
|
||||
### Supported update paths
|
||||
|
||||
### 所支持的升级路径
|
||||
|
||||
In alignment with the versioning scheme described above, we commit to support the following update paths:
|
||||
|
||||
主版本包含重要的新特性,其中的部分特性在升级时会需要由开发人员提供少量的协助才能完成。当升级到新的主版本时,你可能需要运行升级脚本、重构代码、运行其它测试以及学习新的 API。
|
||||
为了和上面所讲的版本方案一致,我们承诺支持如下升级路径:
|
||||
|
||||
* If you are updating within the **same major version,** then you can skip any intermediate versions and update directly to the targeted version. For example, you can update directly from 7.0.0 to 7.2.11.
|
||||
|
||||
小版本包含新的小型特性。小版本是完全向后兼容的,在升级期间,不需要开发人员提供协助,但是你可以(可选的)修改你的应用和库,来使用本次发布中新增的 API、特性和能力。我们会扩展库同级(peer dependency)中的小版本号范围来更新库同级,但并不需要你的项目也更新那些依赖。
|
||||
如果你在**同一个主版本**内升级,那么你可以跳过任何中间版本,直接升级到目标版本。比如,你可以直接从 7.0.0 升级到 7.2.11。
|
||||
|
||||
* If you are updating from **one major version to another,** then we recommend that you **don't skip major versions.** Follow the instructions to incrementally update to the next major version, testing and validating at each step. For example, if you want to update from version 6.x.x to version 8.x.x, we recommend that you update to the latest 7.x.x release first. After successfully updating to 7.x.x, you can then update to 8.x.x.
|
||||
|
||||
如果你要从一个主版本升级到另一个主版本,那么我们建议你不要跳过主版本。要遵循本升级指南,依次升级到下一个主版本,在每一个步骤做完后都测试并验证一下。比如,如果你要从 6.x.x 升级到 8.x.x,我们建议你先升级到 7.x.x 中的最新版。在成功升级到 7.x.x 后,你就可以升级到 8.x.x 了。
|
||||
如果你要从一个主版本升级到另一个主版本,那么我们建议你不要跳过主版本。要遵循本升级指南,依次升级到下一个主版本,在每一个步骤做完后都测试并验证一下。比如,如果你要从 6.x.x 升级到 8.x.x,我们建议你先升级到 7.x.x 中的最新版。在成功升级到 7.x.x 后,你就可以升级到 8.x.x 了。
|
||||
|
||||
See [Keeping Up-to-Date](guide/updating "Updating your projects") for more information about updating your Angular projects to the most recent version.
|
||||
|
||||
@ -172,7 +177,7 @@ All of our major releases are supported for 18 months.
|
||||
|
||||
The following table provides the status for Angular versions under support.
|
||||
|
||||
下表中提供了 Angular 5.0.0 以上的支持状态和一些关键时间点。
|
||||
下表中提供了目前受支持的 Angular 版本的状态。
|
||||
|
||||
Version | Status | Released | Active Ends | LTS Ends
|
||||
------- | ------ | ------------ | ------------ | ------------
|
||||
@ -198,7 +203,7 @@ Sometimes "breaking changes", such as the removal of support for selec
|
||||
|
||||
To make these transitions as easy as possible, we make these commitments to you:
|
||||
|
||||
要让这些转变尽可能的简单,我们会给你两项保证:
|
||||
要让这些转变尽可能的简单,我们会给你下列保证:
|
||||
|
||||
* We work hard to minimize the number of breaking changes and to provide migration tools when possible.
|
||||
|
||||
|
@ -133,7 +133,7 @@ The following example creates five route definitions, configures the router via
|
||||
and adds the result to the `AppModule`'s `imports` array.
|
||||
|
||||
路由器需要先配置才会有路由信息。
|
||||
下面的例子创建了五个路由定义,并用 `RouterModule.forRoot` 方法来配置路由器,
|
||||
下面的例子创建了五个路由定义,并用 `RouterModule.forRoot()` 方法来配置路由器,
|
||||
并把它的返回值添加到 `AppModule` 的 `imports` 数组中。
|
||||
|
||||
<code-example path="router/src/app/app.module.0.ts" linenums="false" header="src/app/app.module.ts (excerpt)">
|
||||
@ -146,7 +146,7 @@ The `appRoutes` array of *routes* describes how to navigate.
|
||||
Pass it to the `RouterModule.forRoot()` method in the module `imports` to configure the router.
|
||||
|
||||
这里的路由数组 `appRoutes` 描述如何进行导航。
|
||||
把它传给 `RouterModule.forRoot` 方法并传给本模块的 `imports` 数组就可以配置路由器。
|
||||
把它传给 `RouterModule.forRoot()` 方法并传给本模块的 `imports` 数组就可以配置路由器。
|
||||
|
||||
Each `Route` maps a URL `path` to a component.
|
||||
There are _no leading slashes_ in the _path_.
|
||||
@ -1378,7 +1378,7 @@ In order to use the Router, you must first register the `RouterModule` from the
|
||||
|
||||
**Note:** The `RouterModule.forRoot` method is a pattern used to register application-wide providers. Read more about application-wide providers in the [Singleton services](guide/singleton-services#forRoot-router) guide.
|
||||
|
||||
**注意:** `RouterModule.forRoot` 方法是用于注册全应用级提供商的编码模式。要详细了解全应用级提供商,参见[单例服务](guide/singleton-services#forroot) 一章。
|
||||
**注意:** `RouterModule.forRoot` 方法是用于注册全应用级提供商的编码模式。要详细了解全应用级提供商,参见[单例服务](guide/singleton-services#forRoot-router) 一章。
|
||||
|
||||
</div>
|
||||
|
||||
@ -1621,7 +1621,8 @@ You've learned how to do the following:
|
||||
|
||||
* Configure the router module with `RouterModule.forRoot()`.
|
||||
|
||||
用 `RouterModule.forRoot` 配置路由器模块
|
||||
用 `RouterModule.forRoot()` 配置路由器模块
|
||||
|
||||
* Set the router to compose HTML5 browser URLs.
|
||||
|
||||
设置路由器,使其合成 HTML5 模式的浏览器 URL
|
||||
@ -1920,7 +1921,7 @@ Import the `CrisisListComponent`, `HeroListComponent`, and `PageNotFoundComponen
|
||||
just like you did in the `app.module.ts`. Then move the `Router` imports
|
||||
and routing configuration, including `RouterModule.forRoot()`, into this routing module.
|
||||
|
||||
导入 `CrisisListComponent`、`HeroListComponent` 和 `PageNotFoundCompponent` 组件,就像 `app.module.ts` 中那样。然后把 `Router` 的导入语句和路由配置以及 `RouterModule.forRoot` 移入这个路由模块中。
|
||||
导入 `CrisisListComponent`、`HeroListComponent` 和 `PageNotFoundCompponent` 组件,就像 `app.module.ts` 中那样。然后把 `Router` 的导入语句和路由配置以及 `RouterModule.forRoot()` 移入这个路由模块中。
|
||||
|
||||
Re-export the Angular `RouterModule` by adding it to the module `exports` array.
|
||||
By re-exporting the `RouterModule` here the components declared in `AppModule` will have access to router directives such as `RouterLink` and `RouterOutlet`.
|
||||
@ -2106,6 +2107,7 @@ Follow these steps:
|
||||
* Change the `selector` to `app-hero-list`.
|
||||
|
||||
把 `selector` 改为 `app-hero-list`。
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Selectors are **not required** for _routed components_ due to the components are dynamically inserted when the page is rendered, but are useful for identifying and targeting them in your HTML element tree.
|
||||
@ -2153,8 +2155,7 @@ When you're done, you'll have these *hero management* files:
|
||||
<div class='children'>
|
||||
|
||||
<div class='file'>
|
||||
|
||||
hero-detail
|
||||
hero-detail
|
||||
</div>
|
||||
|
||||
<div class='children'>
|
||||
@ -2167,15 +2168,14 @@ hero-detail
|
||||
hero-detail.component.html
|
||||
</div>
|
||||
|
||||
<div class='file'> hero-detail.component.ts
|
||||
|
||||
</div>
|
||||
<div class='file'>
|
||||
hero-detail.component.ts
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class='file'>
|
||||
|
||||
hero-list
|
||||
hero-list
|
||||
</div>
|
||||
|
||||
<div class='children'>
|
||||
@ -2188,9 +2188,9 @@ hero-list
|
||||
hero-list.component.html
|
||||
</div>
|
||||
|
||||
<div class='file'> hero-list.component.ts
|
||||
|
||||
</div></div>
|
||||
<div class='file'>
|
||||
hero-list.component.ts
|
||||
</div></div>
|
||||
|
||||
<div class='file'>
|
||||
|
||||
@ -2272,7 +2272,7 @@ Only call `RouterModule.forRoot()` in the root `AppRoutingModule`
|
||||
(or the `AppModule` if that's where you register top level application routes).
|
||||
In any other module, you must call the **`RouterModule.forChild`** method to register additional routes.
|
||||
|
||||
只在根模块 `AppRoutingModule` 中调用 `RouterModule.forRoot`(如果在 `AppModule` 中注册应用的顶级路由,那就在 `AppModule` 中调用)。
|
||||
只在根模块 `AppRoutingModule` 中调用 `RouterModule.forRoot()`(如果在 `AppModule` 中注册应用的顶级路由,那就在 `AppModule` 中调用)。
|
||||
在其它模块中,你就必须调用**`RouterModule.forChild`**方法来注册附属路由。
|
||||
|
||||
</div>
|
||||
@ -3173,7 +3173,7 @@ For the `@routeAnimation` transitions to key off states, you'll need to provide
|
||||
|
||||
The `@routeAnimation` property is bound to the `getAnimationData` with the provided `routerOutlet` reference, so you'll need to define that function in the `AppComponent`. The `getAnimationData` function returns the animation property from the `data` provided through the `ActivatedRoute`. The `animation` property matches the `transition` names you used in the `slideInAnimation` defined in `animations.ts`.
|
||||
|
||||
`@routeAnimation` 属性绑定到了 `getAnimationData` 和 `routerOutlet` 的引用,因此你需要在 `AppComponent` 中定义那个函数。`getAnimationData` 函数根据 `ActivatedRoute` 所提供的 `data` 对象返回动画的属性。`animation` 属性会匹配你在 `animations.ts` 中定义 `slideDownAnimation` 时使用的 `transition` 名称。
|
||||
`@routeAnimation` 属性使用所提供的 `routerOutlet` 引用来绑定到 `getAnimationData`,因此你需要在 `AppComponent` 中定义那个函数。`getAnimationData` 函数会根据 `ActivatedRoute` 所提供的 `data` 对象返回动画的属性。`animation` 属性会根据你在 `animations.ts` 中定义 `slideInAnimation` 时使用的 `transition` 名称进行匹配。
|
||||
|
||||
<code-example path="router/src/app/app.component.2.ts" linenums="false" header="src/app/app.component.ts (router outlet)" region="function-binding">
|
||||
|
||||
@ -3708,7 +3708,7 @@ by default, so the `Crisis Detail` component will be re-used as you select diffe
|
||||
In contrast, back in the `Hero Detail` route, [the component was recreated](#snapshot-the-no-observable-alternative) each time you selected a different hero from the list of heroes.
|
||||
|
||||
`Crisis Detail` 路由是 `Crisis List` 的子路由。由于路由器默认会[复用组件](#reuse),因此当你选择了另一个危机时,`CrisisDetailComponent` 会被复用。
|
||||
作为对比,回到 `Hero Detail` 路由时,每当你选择了不同的英雄时,该组件都会被重新创建。
|
||||
作为对比,回头看看 `Hero Detail` 路由,每当你从列表中选择了不同的英雄时,[都会重新创建该组件](#snapshot-the-no-observable-alternative)。
|
||||
|
||||
At the top level, paths that begin with `/` refer to the root of the application.
|
||||
But child routes *extend* the path of the parent route.
|
||||
@ -5240,7 +5240,7 @@ Add an `anchor` element so you can jump to a certain point on the page.
|
||||
|
||||
Add the `NavigationExtras` object to the `router.navigate()` method that navigates you to the `/login` route.
|
||||
|
||||
为 `router.navigate` 方法添加一个 `NavigationExtras` 对象,用来导航到 `/login` 路由。
|
||||
为 `router.navigate()` 方法添加一个 `NavigationExtras` 对象,用来导航到 `/login` 路由。
|
||||
|
||||
<code-example path="router/src/app/auth/auth.guard.4.ts" linenums="false" header="src/app/auth/auth.guard.ts (v3)">
|
||||
|
||||
@ -5252,7 +5252,7 @@ second argument in the `router.navigateUrl()` function
|
||||
and provide the `queryParamsHandling` and `preserveFragment` to pass along the current query parameters
|
||||
and fragment to the next route.
|
||||
|
||||
还可以在导航之间**保留**查询参数和片段,而无需再次在导航中提供。在 `LoginComponent` 中的 `router.navigate` 方法中,添加一个对象作为第二个参数,该**对象**提供了 `queryParamsHandling` 和 `preserveFragment`,用于传递当前的查询参数和片段到下一个路由。
|
||||
还可以在导航之间**保留**查询参数和片段,而无需再次在导航中提供。在 `LoginComponent` 中的 `router.navigateUrl()` 方法中,添加一个对象作为第二个参数,该**对象**提供了 `queryParamsHandling` 和 `preserveFragment`,用于传递当前的查询参数和片段到下一个路由。
|
||||
|
||||
<code-example path="router/src/app/auth/login/login.component.ts" linenums="false" header="src/app/auth/login/login.component.ts (preserve)" region="preserve">
|
||||
|
||||
@ -5624,9 +5624,9 @@ The second argument in the `RouterModule.forRoot()` method takes an object for a
|
||||
The `preloadingStrategy` is one of those options.
|
||||
Add the `PreloadAllModules` token to the `forRoot()` call:
|
||||
|
||||
`RouterModule.forRoot` 方法的第二个参数接受一个附加配置选项对象。
|
||||
`RouterModule.forRoot()` 方法的第二个参数接受一个附加配置选项对象。
|
||||
`preloadingStrategy` 就是其中之一。
|
||||
把 `PreloadAllModules` 添加到 `forRoot` 调用中:
|
||||
把 `PreloadAllModules` 添加到 `forRoot()` 调用中:
|
||||
|
||||
<code-example path="router/src/app/app-routing.module.6.ts" linenums="false" header="src/app/app-routing.module.ts (preload all)" region="forRoot">
|
||||
|
||||
@ -5699,9 +5699,9 @@ Set the `data.preload` flag in the `crisis-center` route in the `AppRoutingModul
|
||||
|
||||
</code-example>
|
||||
|
||||
Generate a new `SelectivePreloadingStrategyService` service.
|
||||
Generate a new `SelectivePreloadingStrategy` service.
|
||||
|
||||
生成一个新的 `SelectivePreloadingStrategyService` 服务。
|
||||
生成一个新的 `SelectivePreloadingStrategy` 服务。
|
||||
|
||||
<code-example language="none" class="code-shell">
|
||||
ng generate service selective-preloading-strategy
|
||||
@ -5761,7 +5761,8 @@ But first, make a few changes to the `AppRoutingModule`.
|
||||
|
||||
1. Replace the `PreloadAllModules` strategy in the call to `forRoot()` with this `SelectivePreloadingStrategyService`.
|
||||
|
||||
把 `PreloadAllModules` 策略替换成对 `forRoot` 的调用,并且传入这个 `SelectivePreloadingStrategyService`。
|
||||
把 `PreloadAllModules` 策略替换成对 `forRoot()` 的调用,并且传入这个 `SelectivePreloadingStrategyService`。
|
||||
|
||||
1. Add the `SelectivePreloadingStrategyService` strategy to the `AppRoutingModule` providers array so it can be injected
|
||||
elsewhere in the app.
|
||||
|
||||
@ -6125,7 +6126,7 @@ The `RouterModule.forRoot()` function sets the `LocationStrategy` to the `PathLo
|
||||
making it the default strategy.
|
||||
You can switch to the `HashLocationStrategy` with an override during the bootstrapping process if you prefer it.
|
||||
|
||||
`RouterModule.forRoot` 函数把 `LocationStrategy` 设置成了 `PathLocationStrategy`,使其成为了默认策略。
|
||||
`RouterModule.forRoot()` 函数把 `LocationStrategy` 设置成了 `PathLocationStrategy`,使其成为了默认策略。
|
||||
你可以在启动过程中改写(override)它,来切换到 `HashLocationStrategy` 风格 —— 如果你更喜欢这种。
|
||||
|
||||
<div class="alert is-helpful">
|
||||
@ -6278,7 +6279,7 @@ You can go old-school with the `HashLocationStrategy` by
|
||||
providing the `useHash: true` in an object as the second argument of the `RouterModule.forRoot()`
|
||||
in the `AppModule`.
|
||||
|
||||
你可以在根模块的 `RouterModule.forRoot` 的第二个参数中传入一个带有 `useHash: true` 的对象,以回到基于 `HashLocationStrategy` 的传统方式。
|
||||
你可以在根模块的 `RouterModule.forRoot()` 的第二个参数中传入一个带有 `useHash: true` 的对象,以回到基于 `HashLocationStrategy` 的传统方式。
|
||||
|
||||
<code-example path="router/src/app/app.module.6.ts" linenums="false" header="src/app/app.module.ts (hash URL strategy)">
|
||||
|
||||
|
@ -352,7 +352,7 @@ Angular Service Worker 可以使用两种缓存策略之一来获取数据资源
|
||||
|
||||
* `performance`, the default, optimizes for responses that are as fast as possible. If a resource exists in the cache, the cached version is used, and no network request is made. This allows for some staleness, depending on the `maxAge`, in exchange for better performance. This is suitable for resources that don't change often; for example, user avatar images.
|
||||
|
||||
`performance`,默认值,为尽快给出响应而优化。如果缓存中存在某个资源,则使用这个缓存版本。
|
||||
`performance`,默认值,为尽快给出响应而优化。如果缓存中存在某个资源,则使用这个缓存版本,而不再发起网络请求。
|
||||
它允许资源有一定的陈旧性(取决于 `maxAge`)以换取更好的性能。适用于那些不经常改变的资源,例如用户头像。
|
||||
|
||||
* `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.
|
||||
|
@ -534,7 +534,7 @@ for `ngsw.json` returns a `404`, then the service worker
|
||||
removes all of its caches and de-registers itself,
|
||||
essentially self-destructing.
|
||||
|
||||
要停用 Service Worker,请删除或重命名 `ngsw-config.json` 文件。
|
||||
要停用 Service Worker,请删除或重命名 `ngsw.json` 文件。
|
||||
当 Service Worker 对 `ngsw.json` 的请求返回 `404` 时,Service Worker 就会删除它的所有缓存并注销自己,本质上就是自毁。
|
||||
|
||||
### Safety Worker
|
||||
|
@ -35,6 +35,7 @@ The above command completes the following actions:
|
||||
1. Adds the `@angular/service-worker` package to your project.
|
||||
|
||||
把 @angular/service-worker 添加到你的项目中。
|
||||
|
||||
2. Enables service worker build support in the CLI.
|
||||
|
||||
在 CLI 中启用 Service Worker 的构建支持。
|
||||
|
@ -95,7 +95,7 @@ then loading the module in multiple feature modules would duplicate the registra
|
||||
|
||||
There are multiple ways to prevent this:
|
||||
|
||||
有多重方式来防止这种现象:
|
||||
有多种方式来防止这种现象:
|
||||
|
||||
* Use the [`providedIn` syntax](guide/singleton-services#providedIn) instead of registering the service in the module.
|
||||
|
||||
@ -172,9 +172,9 @@ a simple object with the following properties:
|
||||
|
||||
`forRoot()` 会接受一个服务配置对象,并返回一个 [ModuleWithProviders](api/core/ModuleWithProviders) 对象,它带有下列属性:
|
||||
|
||||
* `ngModule`: in this example, the `CoreModule` class.
|
||||
* `ngModule`: in this example, the `GreetingModule` class.
|
||||
|
||||
`ngModule`:在这个例子中,就是 `CoreModule` 类。
|
||||
`ngModule`:在这个例子中,就是 `GreetingModule` 类。
|
||||
|
||||
* `providers`: the configured providers.
|
||||
|
||||
@ -191,20 +191,19 @@ of imported modules.
|
||||
|
||||
在这个 <live-example name="ngmodules">在线例子</live-example>中,根模块 `AppModule` 导入了 `GreetingModule`,并把它的 `providers` 添加到了 `AppModule` 的服务提供商列表中。特别是,Angular 会把所有从其它模块导入的提供商追加到本模块的 `@NgModule.providers` 中列出的提供商之前。这种顺序可以确保你在 `AppModule` 的 `providers` 中显式列出的提供商,其优先级高于导入模块中给出的提供商。
|
||||
|
||||
Import `CoreModule` and use its `forRoot()` method one time, in `AppModule`, because it registers services and you only want to register those services one time in your app. If you were to register them more than once, you could end up with multiple instances of the service and a runtime error.
|
||||
The sample app imports `GreetingModule` and uses its `forRoot()` method one time, in `AppModule`. Registering it once like this prevents multiple instances.
|
||||
|
||||
应该只在 `AppModule` 中导入 `CoreModule` 并只使用一次 `forRoot()` 方法,因为该方法中会注册服务,而你希望那些服务在该应用中只注册一次。
|
||||
如果你多次注册它们,就可能会得到该服务的多个实例,并导致运行时错误。
|
||||
在这个范例应用中,导入 `GreetingModule`,并只在 `AppModule` 中调用一次它的 `forRoot()` 方法。像这样注册它一次就可以防止出现多个实例。
|
||||
|
||||
You can also add a `forRoot()` method in the `GreetingModule` that configures
|
||||
the greeting `UserService`.
|
||||
|
||||
你还可以在 `CoreModule` 中添加一个用于配置 `UserService` 的 `forRoot()` 方法。
|
||||
你还可以在 `GreetingModule` 中添加一个用于配置 `UserService` 的 `forRoot()` 方法。
|
||||
|
||||
In the following example, the optional, injected `UserServiceConfig`
|
||||
extends the greeting `UserService`. If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
|
||||
|
||||
在下面的例子中,可选的注入 `UserServiceConfig` 扩展了 `Core` 模块中的 `UserService`。如果 `UserServiceConfig` 存在,就从这个配置中设置用户名。
|
||||
在下面的例子中,可选的注入 `UserServiceConfig` 扩展了 `UserService`。如果 `UserServiceConfig` 存在,就从这个配置中设置用户名。
|
||||
|
||||
<code-example path="ngmodules/src/app/greeting/user.service.ts" region="ctor" header="src/app/greeting/user.service.ts (constructor)" linenums="false">
|
||||
|
||||
@ -221,7 +220,7 @@ Here's `forRoot()` that takes a `UserServiceConfig` object:
|
||||
Lastly, call it within the `imports` list of the `AppModule`. In the following
|
||||
snippet, other parts of the file are left out. For the complete file, see the <live-example name="ngmodules"></live-example>, or continue to the next section of this document.
|
||||
|
||||
最后,在 `AppModule` 的 `imports`*列表*中调用它。
|
||||
最后,在 `AppModule` 的 `imports`*列表*中调用它。在下面的代码片段中,省略了文件的另一部分。要查看完整文件,参见 <live-example name="ngmodules"></live-example> 或继续阅读本文档的后续章节。
|
||||
|
||||
<code-example path="ngmodules/src/app/app.module.ts" region="import-for-root" header="src/app/app.module.ts (imports)" linenums="false">
|
||||
|
||||
@ -235,22 +234,20 @@ Remember to import `GreetingModule` as a Javascript import at the top of the fil
|
||||
|
||||
记住:在本文件的顶部要以 JavaScript import 形式导入 `GreetingModule`,并且不要把它多次加入到本 `@NgModule` 的 `imports` 列表中。
|
||||
|
||||
<!-- KW--Does this mean that if we need it elsewhere we only import it at the top? I thought the services would all be available since we were importing it into `AppModule` in `providers`. -->
|
||||
## Prevent reimport of the `GreetingModule`
|
||||
|
||||
## Prevent reimport of the `CoreModule`
|
||||
## 防止重复导入 `GreetingModule`
|
||||
|
||||
## 防止重复导入 `CoreModule`
|
||||
|
||||
Only the root `AppModule` should import the `CoreModule`. If a
|
||||
Only the root `AppModule` should import the `GreetingModule`. If a
|
||||
lazy-loaded module imports it too, the app can generate
|
||||
[multiple instances](guide/ngmodule-faq#q-why-bad) of a service.
|
||||
|
||||
只有根模块 `AppModule` 才能导入 `CoreModule`。如果一个惰性加载模块也导入了它,
|
||||
只有根模块 `AppModule` 才能导入 `GreetingModule`。如果一个惰性加载模块也导入了它,
|
||||
该应用就会为服务生成[多个实例](guide/ngmodule-faq#q-why-bad)。
|
||||
|
||||
To guard against a lazy loaded module re-importing `GreetingModule`, add the following `GreetingModule` constructor.
|
||||
|
||||
要想防止惰性加载模块重复导入 `CoreModule`,可以添加如下的 `CoreModule` 构造函数。
|
||||
要想防止惰性加载模块重复导入 `GreetingModule`,可以添加如下的 `GreetingModule` 构造函数。
|
||||
|
||||
<code-example path="ngmodules/src/app/greeting/greeting.module.ts" region="ctor" header="src/app/greeting/greeting.module.ts" linenums="false">
|
||||
|
||||
@ -282,7 +279,7 @@ and the constructor concludes uneventfully.
|
||||
|
||||
It's a different story if you improperly import `GreetingModule` into a lazy loaded module such as `CustomersModule`.
|
||||
|
||||
但如果你把 `CoreModule` 导入到像 `CustomerModule` 这样的惰性加载模块中,事情就不一样了。
|
||||
但如果你把 `GreetingModule` 导入到像 `CustomerModule` 这样的惰性加载模块中,事情就不一样了。
|
||||
|
||||
Angular creates a lazy loaded module with its own injector,
|
||||
a child of the root injector.
|
||||
@ -290,7 +287,7 @@ a child of the root injector.
|
||||
Of course it finds the instance imported by the root `AppModule`.
|
||||
Now `parentModule` exists and the constructor throws the error.
|
||||
|
||||
Angular 创建惰性加载模块时会给它一个自有的注入器,它是根注入器的*子注入器*。
|
||||
Angular 创建惰性加载模块时会给它一个自己的注入器,它是根注入器的*子注入器*。
|
||||
`@SkipSelf()` 让 Angular 在其父注入器中查找 `CoreModule`,这次,它的父注入器是根注入器(而上次的父注入器是空)。
|
||||
当然,这次它找到了由根模块 `AppModule` 导入的实例。
|
||||
该构造函数检测到存在 `parentModule`,于是抛出一个错误。
|
||||
|
@ -933,7 +933,9 @@ As always, strive for consistency.
|
||||
|
||||
<div class="s-rule do">
|
||||
|
||||
**Do** use a hyphenated, lowercase element selector value ; for example, `admin-users`.**坚持**使用带连字符的小写元素选择器值(例如 `admin-users`)。
|
||||
**Do** use a hyphenated, lowercase element selector value; for example, `admin-users`.
|
||||
|
||||
**坚持**使用带连字符的小写元素选择器值(例如 `admin-users`)。
|
||||
|
||||
</div>
|
||||
|
||||
@ -1663,7 +1665,7 @@ Have a consistent set of coding, naming, and whitespace conventions.
|
||||
|
||||
**Do** use upper camel case, also known as PascalCase, when naming classes.
|
||||
|
||||
**坚持**使用大写驼峰命名法来命名类。
|
||||
**坚持**使用大写驼峰形式(也叫 Pascal 形式)来命名类。
|
||||
|
||||
</div>
|
||||
|
||||
@ -2738,11 +2740,12 @@ and more difficult in a flat structure.
|
||||
|
||||
</div>
|
||||
|
||||
<div >
|
||||
<div>
|
||||
|
||||
For more information, refer to <a href="#file-tree">this folder and file structure example.</a>
|
||||
|
||||
<a href="#file-tree">点这里查看目录和文件结构的范例</a>
|
||||
欲知详情,参见<a href="#file-tree">目录和文件结构的范例</a>
|
||||
|
||||
</div>
|
||||
|
||||
<a href="#toc">Back to top</a>
|
||||
@ -3148,7 +3151,7 @@ Yet there is a real danger of that happening if the `SharedModule` provides a se
|
||||
|
||||
### Lazy Loaded folders
|
||||
|
||||
### 核心特性模块
|
||||
### 惰性加载文件夹
|
||||
|
||||
#### Style 04-11
|
||||
|
||||
|
@ -237,10 +237,12 @@ In the following snippets, the `recommended` within double curly braces and the
|
||||
|
||||
An expression may also refer to properties of the _template's_ context
|
||||
such as a template input variable,
|
||||
<!-- link to built-in-directives#template-input-variables -->
|
||||
`let customer`, or a template reference variable, `#customerInput`.
|
||||
<!-- link to guide/template-ref-variables -->
|
||||
|
||||
表达式的上下文可以包括组件之外的对象。
|
||||
比如[模板输入变量](guide/template-syntax#template-input-variable) (`let customer`)和[模板引用变量](guide/template-syntax#ref-vars)(`#customerInput`)就是备选的上下文对象之一。
|
||||
比如[模板输入变量](built-in-directives#template-input-variables) (`let customer`)和[模板引用变量](guide/template-ref-variables)(`#customerInput`)就是备选的上下文对象之一。
|
||||
|
||||
<code-example path="interpolation/src/app/app.component.html" region="template-input-variable" header="src/app/app.component.html (template input variable)" linenums="false">
|
||||
</code-example>
|
||||
@ -3266,13 +3268,13 @@ You'll need this template operator when you turn on strict null checks. It's opt
|
||||
|
||||
### The `$any()` type cast function
|
||||
|
||||
## 类型转换函数 `$any` ($any( <表达式> ))
|
||||
## 类型转换函数 `$any()`
|
||||
|
||||
Sometimes a binding expression triggers a type error during [AOT compilation](guide/aot-compiler) and it is not possible or difficult
|
||||
to fully specify the type. To silence the error, you can use the `$any()` cast function to cast
|
||||
the expression to [the `any` type](http://www.typescriptlang.org/docs/handbook/basic-types.html#any) as in the following example:
|
||||
|
||||
有时候,绑定表达式可能会报类型错误,并且它不能或很难指定类型。要消除这种报错,你可以使用 `$any` 转换函数来把表达式转换成 [`any` 类型](http://www.typescriptlang.org/docs/handbook/basic-types.html#any)。
|
||||
有时候,绑定表达式可能会在 [AOT 编译](guide/aot-compiler)时报类型错误,并且它不能或很难指定类型。要消除这种报错,你可以使用 `$any()` 转换函数来把表达式转换成 [`any` 类型](http://www.typescriptlang.org/docs/handbook/basic-types.html#any),范例如下:
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-1" header="src/app/app.component.html" linenums="false">
|
||||
</code-example>
|
||||
@ -3281,12 +3283,12 @@ When the Angular compiler turns this template into TypeScript code,
|
||||
it prevents TypeScript from reporting that `bestByDate` is not a member of the `item`
|
||||
object when it runs type checking on the template.
|
||||
|
||||
在这个例子中,当 Angular 编译器把模板转换成 TypeScript 代码时,`$any` 表达式可以防止 TypeScript 编译器报错说 `marker` 不是 `Hero` 接口的成员。
|
||||
当 Angular 编译器把模板转换成 TypeScript 代码时,`$any` 表达式可以防止 TypeScript 编译器在进行类型检查时报错说 `bestByDate` 不是 `item` 对象的成员。
|
||||
|
||||
The `$any()` cast function also works with `this` to allow access to undeclared members of
|
||||
the component.
|
||||
|
||||
`$any` 转换函数可以和 `this` 联合使用,以便访问组件中未声明过的成员。
|
||||
`$any()` 转换函数可以和 `this` 联合使用,以便访问组件中未声明过的成员。
|
||||
|
||||
<code-example path="built-in-template-functions/src/app/app.component.html" region="any-type-cast-function-2" header="src/app/app.component.html" linenums="false">
|
||||
</code-example>
|
||||
|
@ -35,16 +35,28 @@ The CLI schematic `@nguniversal/express-engine` performs the required steps, as
|
||||
</div>
|
||||
|
||||
{@a the-example}
|
||||
## Universal tutorial
|
||||
|
||||
## Universal tutorial
|
||||
|
||||
## Universal 教程
|
||||
|
||||
|
||||
The [Tour of Heroes tutorial](tutorial) is the foundation for this walkthrough.
|
||||
|
||||
这次演练的基础是[“英雄指南”教程](tutorial) 。
|
||||
|
||||
In this example, the Angular CLI compiles and bundles the Universal version of the app with the
|
||||
[Ahead-of-Time (AoT) compiler](guide/aot-compiler).
|
||||
A Node Express web server compiles HTML pages with Universal based on client requests.
|
||||
|
||||
在这个例子中,Angular CLI 使用 [预先(AoT)编译器](guide/aot-compiler)编译并打包了该应用的 Universal 版本。 Node Express Web 服务器则会根据客户端的请求,利用 Universal 编译 HTML 页面。
|
||||
|
||||
|
||||
To create the server-side app module, `app.server.module.ts`, run the following CLI command.
|
||||
|
||||
要创建服务端应用模块 `app.server.module.ts`,请运行以下 CLI 命令。
|
||||
|
||||
|
||||
<code-example format="." language="bash">
|
||||
|
||||
ng add @nguniversal/express-engine --clientProject angular.io-example
|
||||
@ -53,6 +65,9 @@ ng add @nguniversal/express-engine --clientProject angular.io-example
|
||||
|
||||
The command creates the following folder structure.
|
||||
|
||||
该命令会创建如下文件夹结构。
|
||||
|
||||
|
||||
<code-example format="." language="none" linenums="false">
|
||||
src/
|
||||
index.html <i>app web page</i>
|
||||
@ -72,10 +87,19 @@ webpack.server.config.js <i>* webpack server configuration</i>
|
||||
|
||||
The files marked with `*` are new and not in the original tutorial sample.
|
||||
|
||||
标有 `*` 的文件都是新增的,不在原始的教程示例中。
|
||||
|
||||
|
||||
### Universal in action
|
||||
|
||||
### Universal 实战
|
||||
|
||||
|
||||
To start rendering your app with Universal on your local system, use the following command.
|
||||
|
||||
要使用 Universal 在本地系统中渲染你的应用,请使用如下命令。
|
||||
|
||||
|
||||
<code-example format="." language="bash" linenums="false">
|
||||
npm run build:ssr && npm run serve:ssr
|
||||
</code-example>
|
||||
@ -83,33 +107,75 @@ npm run build:ssr && npm run serve:ssr
|
||||
Open a browser and navigate to http://localhost:4000/.
|
||||
You should see the familiar Tour of Heroes dashboard page.
|
||||
|
||||
打开浏览器,导航到 http://localhost:4000/。你会看到熟悉的“英雄指南”仪表盘页面。
|
||||
|
||||
|
||||
Navigation via `routerLinks` works correctly because they use the native anchor (`<a>`) tags.
|
||||
You can go from the Dashboard to the Heroes page and back.
|
||||
You can click a hero on the Dashboard page to display its Details page.
|
||||
|
||||
通过 `routerLinks` 导航时能正常工作,因为它们使用的是原生的链接标签(`<a>`)。你可以从仪表盘进入 英雄列表页面,然后返回。你可以点击仪表盘页面上的一个英雄来显示他的详情页面。
|
||||
|
||||
|
||||
If you throttle your network speed so that the client-side scripts take longer to download (instructions below),
|
||||
you'll notice:
|
||||
|
||||
如果你限制下网速(稍后会讲操作步骤),让客户端脚本下载时间变长,你会注意到:
|
||||
|
||||
|
||||
* Clicking a hero on the Heroes page does nothing.
|
||||
|
||||
点击英雄列表页面上的英雄没有反应。
|
||||
|
||||
* You can't add or delete a hero.
|
||||
* The search box on the Dashboard page is ignored.
|
||||
* The *Back* and *Save* buttons on the Details page don't work.
|
||||
|
||||
你无法添加或删除英雄。
|
||||
|
||||
- The search box on the Dashboard page is ignored.
|
||||
|
||||
仪表盘页面上的搜索框会被忽略。
|
||||
|
||||
- The *Back* and *Save* buttons on the Details page don't work.
|
||||
|
||||
“详情”页面上的*后退*和*保存*按钮不起作用。
|
||||
|
||||
|
||||
User events other than `routerLink` clicks aren't supported.
|
||||
You must wait for the full client app to bootstrap and run, or buffer the events using libraries like
|
||||
[preboot](https://github.com/angular/preboot), which allow you to replay these events once the client-side scripts load.
|
||||
|
||||
不支持除了点击 `routerLink` 以外的任何用户事件。你必须等待完整的客户端应用启动并运行,或者使用 [preboot 之类的](https://github.com/angular/preboot)库来缓冲这些事件,这样你就可以在客户端脚本加载完毕后重放这些事件。
|
||||
|
||||
|
||||
The transition from the server-rendered app to the client app happens quickly on a development machine, but you should
|
||||
always test your apps in real-world scenarios.
|
||||
|
||||
在开发机器上,从服务端渲染的应用过渡到客户端应用的过程会很快,但是你还是应该在实际场景中测试一下你的应用。
|
||||
|
||||
|
||||
You can simulate a slower network to see the transition more clearly as follows:
|
||||
|
||||
你可以通过模拟速度较慢的网络来更清晰地看到这种转换,如下所示:
|
||||
|
||||
|
||||
1. Open the Chrome Dev Tools and go to the Network tab.
|
||||
|
||||
打开 Chrome 开发者工具,进入 Network 标签页。
|
||||
|
||||
1. Find the [Network Throttling](https://developers.google.com/web/tools/chrome-devtools/network-performance/reference#throttling)
|
||||
dropdown on the far right of the menu bar.
|
||||
dropdown on the far right of the menu bar.
|
||||
|
||||
找一下菜单栏最右侧的 [Network Throttling](https://developers.google.com/web/tools/chrome-devtools/network-performance/reference#throttling) 下拉菜单。
|
||||
|
||||
1. Try one of the "3G" speeds.
|
||||
|
||||
尝试一下 “3G” 的速度吧。
|
||||
|
||||
|
||||
The server-rendered app still launches quickly but the full client app may take seconds to load.
|
||||
|
||||
服务端渲染的应用仍然可以快速启动,但完整的客户端应用可能需要几秒钟才能加载完。
|
||||
|
||||
{@a why-do-it}
|
||||
## Why use server-side rendering?
|
||||
|
||||
@ -121,7 +187,7 @@ There are three main reasons to create a Universal version of your app.
|
||||
|
||||
1. Facilitate web crawlers through [search engine optimization (SEO)](https://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)
|
||||
|
||||
通过[搜索引擎优化(SEO)](https://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)来帮助网络爬虫。
|
||||
通过[搜索引擎优化(SEO)](https://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf)来帮助网络爬虫。
|
||||
|
||||
1. Improve performance on mobile and low-powered devices
|
||||
|
||||
@ -129,7 +195,7 @@ There are three main reasons to create a Universal version of your app.
|
||||
|
||||
1. Show the first page quickly with a [first-contentful paint (FCP)](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint)
|
||||
|
||||
迅速显示出第一个页面
|
||||
迅速显示出第一个支持[首次内容绘制(FCP)](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint)的页面
|
||||
|
||||
{@a seo}
|
||||
|
||||
@ -137,12 +203,13 @@ There are three main reasons to create a Universal version of your app.
|
||||
|
||||
### Facilitate web crawlers (SEO)
|
||||
|
||||
### 帮助网络爬虫
|
||||
### 帮助网络爬虫(SEO)
|
||||
|
||||
Google, Bing, Facebook, Twitter, and other social media sites rely on web crawlers to index your application content and
|
||||
make that content searchable on the web.
|
||||
|
||||
Google、Bing、Facebook、Twitter 和其它社交媒体网站都依赖网络爬虫去索引你的应用内容,并且让它的内容可以通过网络搜索到。
|
||||
|
||||
These web crawlers may be unable to navigate and index your highly interactive Angular application as a human user could do.
|
||||
|
||||
这些网络爬虫可能不会像人类那样导航到你的具有高度交互性的 Angular 应用,并为其建立索引。
|
||||
@ -176,7 +243,7 @@ Displaying the first page quickly can be critical for user engagement.
|
||||
|
||||
快速显示第一页对于吸引用户是至关重要的。
|
||||
|
||||
[53percent of mobile site visits are abandoned](https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/)
|
||||
[53 percent of mobile site visits are abandoned](https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/)
|
||||
if pages take longer than 3 seconds to load.
|
||||
Your app may have to launch faster to engage these users before they decide to do something else.
|
||||
|
||||
@ -230,14 +297,13 @@ The sample web server for this guide is based on the popular [Express](https://e
|
||||
Universal applications use the Angular `platform-server` package (as opposed to `platform-browser`), which provides
|
||||
server implementations of the DOM, `XMLHttpRequest`, and other low-level features that don't rely on a browser.
|
||||
|
||||
要制作一个 Universal 应用,就要安装 `platform-server` 包,它提供了 DOM 的服务端实现、`XMLHttpRequest` 以及其它不依赖浏览器的底层特性。
|
||||
使用 `platform-server` 模块(代替 `platform-browser` 模块)编译客户端应用,并在 Web 服务器上运行其生成的 Universal 应用。
|
||||
Universal 应用使用 `platform-server` 包(而不是 `platform-browser`),它提供了 DOM 的服务端实现、`XMLHttpRequest` 以及其它不依赖浏览器的底层特性。
|
||||
|
||||
The server ([Node Express](https://expressjs.com/) in this guide's example)
|
||||
passes client requests for application pages to the NgUniversal `ngExpressEngine`. Under the hood, this
|
||||
calls Universal's `renderModuleFactory()` function, while providing caching and other helpful utilities.
|
||||
|
||||
服务器(这个例子中使用的是 [Node Express](https://expressjs.com/) 服务器)会把客户端对应用页面的请求传给 `renderModuleFactory()` 函数。
|
||||
服务器(这个例子中使用的是 [Node Express](https://expressjs.com/) 服务器)会把客户端对应用页面的请求传给 NgUniversal 的 `ngExpressEngine`。在内部实现上,它会调用 Universal 的 `renderModuleFactory()` 函数,它还提供了缓存等有用的工具函数。
|
||||
|
||||
The `renderModuleFactory()` function takes as inputs a *template* HTML page (usually `index.html`),
|
||||
an Angular *module* containing components,
|
||||
@ -268,20 +334,20 @@ Finally, the server returns the rendered page to the client.
|
||||
|
||||
Because a Universal app doesn't execute in the browser, some of the browser APIs and capabilities may be missing on the server.
|
||||
|
||||
由于 Universal 的 `platform-server` 应用并没有运行在浏览器中,因此你不得不在该服务器中缺少某些浏览器 API 和能力的情况下工作。
|
||||
由于 Universal 应用并没有运行在浏览器中,因此该服务器上可能会缺少浏览器的某些 API 和其它能力。
|
||||
|
||||
|
||||
For example, server-side applications can't reference browser-only global objects such as `window`, `document`, `navigator`, or `location`.
|
||||
|
||||
比如,服务端应用不能引用浏览器独有的全局对象,比如 `window`、`document`、`navigator` 或 `location`。
|
||||
|
||||
Angular provides some injectable abstractions over these objects, such as [`Location`](api/common/Location)
|
||||
or [`DOCUMENT`](api/common/DOCUMENT); it may substitute adequately for these APIs.
|
||||
If Angular doesn't provide it, it's possible to write new abstractions that delegate to the browser APIs while in the browser
|
||||
and to an alternative implementation while on the server (aka shimming).
|
||||
|
||||
比如,你的服务端渲染页面不能引用浏览器独有的原生对象,比如 `window`、`document`、`navigator` 或 `location`。
|
||||
如果你在服务端渲染的页面中不需要它们,就可以使用条件逻辑跳过它们。
|
||||
另一种方式是查找一个可注入的 Angular 对所需对象的抽象服务,比如 `Location` 或 `Document`,它可能作为你调用的指定 API 的等价替身。
|
||||
如果 Angular 没有提供它,你也可以写一个自己的抽象层,当在浏览器中运行时,就把它委托给浏览器 API,当它在服务器中运行时,就提供一个符合要求的代用实现。
|
||||
Angular 提供了一些这些对象的可注入的抽象层,比如 [`Location`](api/common/Location) 或 [`DOCUMENT`](api/common/DOCUMENT),它可以作为你所调用的 API 的等效替身。
|
||||
如果 Angular 没有提供它,你也可以写一个自己的抽象层,当在浏览器中运行时,就把它委托给浏览器 API,当它在服务器中运行时,就提供一个符合要求的代用实现(也叫垫片 - shimming)。
|
||||
|
||||
|
||||
Similarly, without mouse or keyboard events, a server-side app can't rely on a user clicking a button to show a component.
|
||||
@ -299,14 +365,12 @@ Universal 应用必须仅仅根据客户端过来的请求决定要渲染的内
|
||||
|
||||
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data.
|
||||
These services send requests to _relative_ URLs such as `api/heroes`.
|
||||
|
||||
教程中的 `HeroService` 和 `HeroSearchService` 都委托了 Angular 的 `HttpClient` 模块来获取应用数据。
|
||||
那些服务都把请求发送到了*相对* URL,比如 `api/heroes`。
|
||||
|
||||
In a Universal app, HTTP URLs must be _absolute_(for example, `https://my-server.com/api/heroes`).
|
||||
This means you need to change your services to make requests with absolute URLs when running on the server and with relative
|
||||
URLs when running in the browser.
|
||||
|
||||
教程中的 `HeroService` 和 `HeroSearchService` 都委托了 Angular 的 `HttpClient` 模块来获取应用数据。
|
||||
那些服务都把请求发送到了*相对* URL,比如 `api/heroes`。
|
||||
在 Universal 应用中,HTTP 的 URL 必须是*绝对地址*(比如 `https://my-server.com/api/heroes`),
|
||||
只有这样,Universal 的 Web 服务器才能处理那些请求。
|
||||
这意味着当运行在服务端时,你要修改你的服务,来使用绝对 URL发起请求,而在浏览器中,则使用相对 URL。
|
||||
@ -408,16 +472,14 @@ not using the `Request` token as shown above.
|
||||
|
||||
第二个参数 `extraProviders` 是可选的。它能让你指定一些在服务端运行时特有的服务提供商。
|
||||
只有当你的应用需要一些运行在服务器中才需要的信息时,才需要这么做。
|
||||
这个例子中所需的信息就是正在运行的服务器的*源*地址,它通过 `APP_BASE_HREF` 令牌提供,以便应用可以 [计算出 HTTP URL 的绝对地址](#http-urls)。
|
||||
比如这个运行中的服务器的*源*地址,当像前面例子中那样无法使用 `Request` 令牌时,可用它来[计算 HTTP URL 的绝对地址](#http-urls)。
|
||||
|
||||
The `ngExpressEngine()` function returns a `Promise` callback that resolves to the rendered page.
|
||||
|
||||
`ngExpressEngine()` 函数返回了一个会解析成渲染好的页面的*承诺(Promise)*。
|
||||
|
||||
It's up to the engine to decide what to do with that page.
|
||||
This engine's `Promise` callback returns the rendered page to the web server,
|
||||
which then forwards it to the client in the HTTP response.
|
||||
|
||||
`ngExpressEngine()` 函数返回了一个会解析成渲染好的页面的*承诺(Promise)*。
|
||||
接下来你的引擎要决定拿这个页面做点什么。
|
||||
在*这个引擎*的 `Promise` 回调函数中,把渲染好的页面返回给了 Web 服务器,然后服务器通过 HTTP 响应把它转发给了客户端。
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Keeping your Angular Projects Up-to-Date
|
||||
|
||||
# 升级你的 Angular 项目
|
||||
# 持续更新你的 Angular 项目
|
||||
|
||||
Just like Web and the entire web ecosystem, Angular is continuously improving. Angular balances continuous improvement with a strong focus on stability and making updates easy. Keeping your Angular app up-to-date enables you to take advantage of leading-edge new features, as well as optimizations and bug fixes.
|
||||
|
||||
|
@ -2117,11 +2117,11 @@ keeping the controllers in AngularJS land.
|
||||
|
||||
In the new version, you import the Angular HTTP module and call its `HttpClient` service instead of `ngResource`.
|
||||
|
||||
在这个新版本中,你导入了 Angular 的 HTTP 模块,并且用它的 `Http` 服务替换掉 `NgResource`。
|
||||
在这个新版本中,你导入了 Angular 的 HTTP 模块,并且用它的 `HttpClient` 服务替换掉 `ngResource`。
|
||||
|
||||
Re-open the `app.module.ts` file, import and add `HttpClientModule` to the `imports` array of the `AppModule`:
|
||||
|
||||
再次打开 `app.module.ts` 文件,导入并把 `HttpModule` 添加到 `AppModule` 的 `imports` 数组中:
|
||||
再次打开 `app.module.ts` 文件,导入并把 `HttpClientModule` 添加到 `AppModule` 的 `imports` 数组中:
|
||||
|
||||
<code-example path="upgrade-phonecat-2-hybrid/app/app.module.ts" region="httpclientmodule" header="app.module.ts">
|
||||
</code-example>
|
||||
@ -2149,7 +2149,7 @@ be injected to it and it is stored as a private field. The service is then
|
||||
used in the two instance methods, one of which loads the list of all phones,
|
||||
and the other loads the details of a specified phone:
|
||||
|
||||
在它的构造函数中,该类期待一个 `Http` 服务。`Http` 服务将被注入进来并存入一个私有字段。
|
||||
在它的构造函数中,该类期待一个 `HttpClient` 服务。`HttpClient` 服务将被注入进来并存入一个私有字段。
|
||||
然后该服务在两个实例方法中被使用到,一个加载所有电话的列表,另一个加载一台指定电话的详情:
|
||||
|
||||
<code-example path="upgrade-phonecat-2-hybrid/app/core/phone/phone.service.ts" region="fullclass" header="app/core/phone/phone.service.ts">
|
||||
|
@ -14,9 +14,11 @@ Angular [工作区](guide/glossary#workspace)根目录下的 `angular.json` 文
|
||||
|
||||
At the top level of `angular.json`, a few properties configure the workspace, and a `projects` section contains the remaining per-project configuration options. CLI defaults set at the workspace level can be overridden by defaults set at the project level, and defaults set at the project level can be overridden on the command line.
|
||||
|
||||
在 `angular.json` 的顶级,一些属性用于配置工作区,其中的 `projects` 区则包含其余的针对每个项目的配置项。CLI 在工作空间级的默认设置可以被项目级的设置所覆盖,而项目级的设置可以被命令行中的设置所覆盖。
|
||||
|
||||
The following properties, at the top level of the file, configure the workspace.
|
||||
|
||||
在 `angular.json` 的顶级,一些属性用于配置工作区,其中的 `projects` 区则包含其余的针对每个项目的配置项。
|
||||
下列属性位于文件的顶级,用于配置工作空间。
|
||||
|
||||
* `version`: The configuration-file version.
|
||||
|
||||
@ -31,13 +33,16 @@ The following properties, at the top level of the file, configure the workspace.
|
||||
`defaultProject`:当命令中没有指定参数时,要使用的默认工程名。当你用 `ng new` 在新的工作区中创建新应用时,该应用就会一直作为此工作区的默认项目,除非你到这里修改它。
|
||||
|
||||
* `schematics` : A set of [schematics](guide/glossary#schematic) that customize the `ng generate` sub-command option defaults for this workspace. See [Generation schematics](#schematics) below.
|
||||
|
||||
`schematics`:一组[原理图](guide/glossary#schematic),用于定制 `ng generate` 子命令在本工作空间中的默认选项。参见稍后的[生成器原理图](#schematics)。
|
||||
|
||||
* `projects` : Contains a subsection for each project (library or application) in the workspace, with the per-project configuration options.
|
||||
|
||||
`projects`:对于工作区中的每个项目(库、应用、e2e 测试)都会包含一个子分区,子分区中是每个项目的配置项。
|
||||
`projects`:对于工作区中的每个项目(应用或库)都会包含一个子分区,子分区中是每个项目的配置项。
|
||||
|
||||
The initial app that you create with `ng new app_name` is listed under "projects":
|
||||
|
||||
你通过 `ng new app_name` 命令创建的初始应用及其对应的端到端测试应用都会列在 `projects` 下:
|
||||
你通过 `ng new app_name` 命令创建的初始应用会列在 `projects` 目录下:
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"projects": {
|
||||
@ -61,11 +66,11 @@ When you create a library project with `ng generate library`, the library projec
|
||||
|
||||
* The initial app created by `ng new` is at the top level of the workspace file structure.
|
||||
|
||||
`ng new` 创建的这个初始应用和它的 e2e 应用一起位于工作区文件结构的顶层。
|
||||
`ng new` 创建的这个初始应用位于工作区文件结构的顶层。
|
||||
|
||||
* Additional applications and libraries go into a `projects` folder in the workspace.
|
||||
|
||||
其它应用、e2e应用和库位于工作区的 `projects` 文件夹中。
|
||||
其它应用和库位于工作区的 `projects` 文件夹中。
|
||||
|
||||
For more information, see [Workspace and project file structure](guide/file-structure).
|
||||
|
||||
@ -143,7 +148,7 @@ The `architect` section of `angular.json` contains a set of Architect *targets*.
|
||||
Many of the targets correspond to the CLI commands that run them.
|
||||
Some additional predefined targets can be run using the `ng run` command, and you can define your own targets.
|
||||
|
||||
建筑师(Architect)是指 CLI 用来根据所提供的配置执行复杂任务(如编译和测试运行)的工具。 `architect` 部分包含一组建筑*目标*。很多目标都对应于运行它们的 CLI 命令。使用 `ng run` 命令可以运行一些额外的预定义目标,并可以定义自己的目标。
|
||||
建筑师(Architect)是指 CLI 用来根据所提供的配置执行复杂任务(如编译和测试运行)的工具。 `angular.json` 的 `architect` 部分包含一组建筑*目标*。很多目标都对应于运行它们的 CLI 命令。使用 `ng run` 命令可以运行一些额外的预定义目标,并可以定义自己的目标。
|
||||
|
||||
Each target object specifies the `builder` for that target, which is the npm package for the tool that Architect runs.
|
||||
In addition, each target has an `options` section that configures default options for the target, and a `configurations` section that names and specifies alternative configurations for the target.
|
||||
@ -226,11 +231,18 @@ The `architect/build` section configures defaults for options of the `ng build`
|
||||
|
||||
### Default build targets
|
||||
|
||||
### 默认的构建目标
|
||||
|
||||
Angular defines default builders for use with the Architect tool and `ng run` command.
|
||||
The default builders provide implementations that use a particular tool to perform a complex operation.
|
||||
|
||||
Angular 定义了一些默认的构建器,供建筑师工具和 `ng run` 命令使用。
|
||||
这些默认的构建器会利用一些特定工具来执行复杂操作。
|
||||
|
||||
The JSON schemas that the define the options and defaults for each of these default builders are collected in the [`@angular-devkit/build-angular`](https://github.com/angular/angular-cli/blob/7.0.x/packages/angular/cli/lib/config/schema.json) package. The schemas configure options for the following Architect build targets:
|
||||
|
||||
这些默认构造器的选项及其默认值的 JSON 模式定义在 [`@angular-devkit/build-angular`](https://github.com/angular/angular-cli/blob/7.0.x/packages/angular/cli/lib/config/schema.json) 包中。这些 JSON 模式包括下列构建目标的配置项:
|
||||
|
||||
* app-shell
|
||||
* browser
|
||||
* dev-server
|
||||
@ -286,9 +298,15 @@ Some additional options (listed below) can only be set through the configuration
|
||||
|
||||
## Project asset configuration
|
||||
|
||||
## 项目资产(asset)配置
|
||||
|
||||
|
||||
Each `build` target configuration can include an `assets` array that lists files or folders you want to copy as-is when building your project.
|
||||
By default, the `src/assets/` folder and `src/favicon.ico` are copied over.
|
||||
|
||||
每个 `build` 目标配置都可以包含一个 `assets` 数组,它列出了当你构建项目时要复制的文件或文件夹。默认情况下,会复制 `src/assets/` 文件夹和 `src/favicon.ico` 。
|
||||
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"assets": [
|
||||
"src/assets",
|
||||
@ -298,16 +316,37 @@ By default, the `src/assets/` folder and `src/favicon.ico` are copied over.
|
||||
|
||||
To exclude an asset, you can remove it from the assets configuration.
|
||||
|
||||
要排除某个资产,可以从这份资产配置中删除它。
|
||||
|
||||
|
||||
You can further configure assets to be copied by specifying assets as objects, rather than as simple paths relative to the workspace root.
|
||||
A asset specification object can have the following fields.
|
||||
|
||||
你可以通过把资产指定为对象的形式来进一步配置要复制的资产,而不仅是相对于工作空间根目录的路径。一个资产对象可以包含如下字段。
|
||||
|
||||
|
||||
* `glob`: A [node-glob](https://github.com/isaacs/node-glob/blob/master/README.md) using `input` as base directory.
|
||||
|
||||
`glob`:一个 [node-glob](https://github.com/isaacs/node-glob/blob/master/README.md) 它使用 `input` 作为基准目录。
|
||||
|
||||
* `input`: A path relative to the workspace root.
|
||||
|
||||
`input`:相对于工作空间根目录的路径。
|
||||
|
||||
* `output`: A path relative to `outDir` (default is `dist/`*project-name*). Because of the security implications, the CLI never writes files outside of the project output path.
|
||||
* `ignore`: A list of globs to exclude.
|
||||
|
||||
`output`:相对于 `outDir` 的路径(默认为 `dist/`*project-name* )。为了杜绝安全隐患,CLI 永远不会在项目输出路径之外写文件。
|
||||
|
||||
- `ignore`: A list of globs to exclude.
|
||||
|
||||
`ignore`:要排除的 glob 列表。
|
||||
|
||||
|
||||
For example, the default asset paths can be represented in more detail using the following objects.
|
||||
|
||||
例如,可以使用如下对象来更详细地表达默认的资产路径。
|
||||
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "src/assets/", "output": "/assets/" },
|
||||
@ -318,6 +357,9 @@ For example, the default asset paths can be represented in more detail using the
|
||||
You can use this extended configuration to copy assets from outside your project.
|
||||
For example, the following configuration copies assets from a node package:
|
||||
|
||||
你可以使用此扩展配置从项目外部复制资产。例如,以下配置会从 node 包中复制资产:
|
||||
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "./node_modules/some-package/images", "output": "/some-package/" },
|
||||
@ -326,8 +368,14 @@ For example, the following configuration copies assets from a node package:
|
||||
|
||||
The contents of `node_modules/some-package/images/` will be available in `dist/some-package/`.
|
||||
|
||||
`node_modules/some-package/images/` 中的内容将会复制到 `dist/some-package/` 中。
|
||||
|
||||
|
||||
The following example uses the `ignore` field to exclude certain files in the assets folder from being copied into the build:
|
||||
|
||||
下面的例子使用 `ignore` 字段排除了 assets 文件夹中的某些特定文件,防止它们被复制到 build 中:
|
||||
|
||||
|
||||
<code-example format="." language="json" linenums="false">
|
||||
"assets": [
|
||||
{ "glob": "**/*", "input": "src/assets/", "ignore": ["**/*.svg"], "output": "/assets/" },
|
||||
|
Loading…
x
Reference in New Issue
Block a user