diff --git a/aio/content/guide/dependency-injection.md b/aio/content/guide/dependency-injection.md index 8827128cc5..222e6379b1 100644 --- a/aio/content/guide/dependency-injection.md +++ b/aio/content/guide/dependency-injection.md @@ -97,7 +97,7 @@ The `@Injectable` decorator is an essential ingredient in every Angular service The rest of the class has been rewritten to expose a `getHeroes` method that returns the same mock data as before. -[`@Injectable` 装饰器](#injectable)是定义每个 Angular 服务时的必备部分。 +`@Injectable` 装饰器是定义每个 Angular 服务时的必备部分。 把该类的其它部分改写为暴露一个返回和以前一样的 mock 数据的 `getHeroes` 方法。 diff --git a/aio/content/marketing/docs.md b/aio/content/marketing/docs.md index 83ba0535b2..aa965f4add 100644 --- a/aio/content/marketing/docs.md +++ b/aio/content/marketing/docs.md @@ -7,56 +7,31 @@ Angular is a platform that makes it easy to build applications with the web. Ang Angular 是一个开发平台。它能帮你更轻松的构建 Web 应用。Angular 集声明式模板、依赖注入、端到端工具和一些最佳实践于一身,为你解决开发方面的各种挑战。Angular 为开发者提升构建 Web、手机或桌面应用的能力。
- -
Get a Glimpse of Angular
-
Angular 走马观花
-

A quick look at an Angular "hello world" application.

-

快速体验 Angular 的 "hello world" 应用。

- - -
- -
Get Going with Angular
-
开始使用 Angular
-

Get going on your own environment with the Quickstart.

-

跟随"快速上手"构建你的开发环境

- - -
- -
Fundamentals
-
基本原理
-

Learn Angular application fundamentals, starting with an architecture overview.

-

学习 Angular 应用的基本原理。
从架构概览开始。

- - -
-
## Assumptions @@ -74,8 +49,9 @@ Most Angular code can be written with just the latest JavaScript, using [types](https://www.typescriptlang.org/docs/handbook/classes.html "TypeScript Types") for dependency injection, and using [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html "Decorators") for metadata. + 本文档假设你已经熟悉了 [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript "Learn JavaScript") 和来自 [最新标准](https://babeljs.io/learn-es2015/ "Latest JavaScript standards") 的一些知识,比如 [类](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes "ES2015 Classes") 和 [模块](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import "ES2015 Modules")。 -下列代码范例都是用最新版本的 JavaScript 写的,利用 [类型](https://www.typescriptlang.org/docs/handbook/classes.html "TypeScript Types") 实现依赖注入,并使用[装饰器](https://www.typescriptlang.org/docs/handbook/decorators.html "Decorators")来提供元数据。 +下列代码范例都是用最新版本的 [TypeScript](https://www.typescriptlang.org/ "TypeScript") 写的,利用 [类型](https://www.typescriptlang.org/docs/handbook/classes.html "TypeScript Types") 实现依赖注入,并使用[装饰器](https://www.typescriptlang.org/docs/handbook/decorators.html "Decorators")来提供元数据。 ## Feedback diff --git a/aio/src/app/documents/document.service.ts b/aio/src/app/documents/document.service.ts index 450a675a32..6b1ba2cab7 100644 --- a/aio/src/app/documents/document.service.ts +++ b/aio/src/app/documents/document.service.ts @@ -5,6 +5,8 @@ import { AsyncSubject, Observable, of } from 'rxjs'; import { catchError, switchMap, tap } from 'rxjs/operators'; import { DocumentContents } from './document-contents'; +import { Logger } from '../shared/logger.service'; +import { LocationService } from '../shared/location.service'; export { DocumentContents } from './document-contents'; diff --git a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts index 76a4d19613..d1b27737f5 100644 --- a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts +++ b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts @@ -1,11 +1,10 @@ -import { Component, ElementRef, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; -import { HostListener } from '@angular/core'; -import { Title, Meta } from '@angular/platform-browser'; +import { Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy, Output } from '@angular/core'; +import { Meta, Title } from '@angular/platform-browser'; import { Observable, of, timer } from 'rxjs'; import { catchError, switchMap, takeUntil, tap } from 'rxjs/operators'; -import { DocumentContents, FILE_NOT_FOUND_ID, FETCHING_ERROR_ID } from 'app/documents/document.service'; +import { DocumentContents, FETCHING_ERROR_ID, FILE_NOT_FOUND_ID } from 'app/documents/document.service'; import { Logger } from 'app/shared/logger.service'; import { TocService } from 'app/shared/toc.service'; import { ElementsLoader } from 'app/custom-elements/elements-loader'; @@ -79,10 +78,10 @@ export class DocViewerComponent implements OnDestroy { } this.docContents$ - .pipe(switchMap(newDoc => this.render(newDoc)), + .pipe(switchMap(newDoc => this.render(newDoc)), takeUntil(this.onDestroy$), - ) - .subscribe(); + ) + .subscribe(); } ngOnDestroy() { @@ -133,23 +132,23 @@ export class DocViewerComponent implements OnDestroy { this.setNoIndex(doc.id === FILE_NOT_FOUND_ID || doc.id === FETCHING_ERROR_ID); return this.void$.pipe( - // Security: `doc.contents` is always authored by the documentation team - // and is considered to be safe. - tap(() => this.nextViewContainer.innerHTML = doc.contents || ''), - tap(() => swapOriginAndResult(this.nextViewContainer)) - .do(() =>addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id)), - switchMap(() => this.elementsLoader.loadContainingCustomElements(this.nextViewContainer)), - tap(() => this.docReady.emit()) - , - switchMap(() => this.swapViews(addTitleAndToc)), - tap(() => this.docRendered.emit()), - catchError(err => { - const errorMessage = (err instanceof Error) ? err.stack : err; - this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`)); - this.nextViewContainer.innerHTML = ''; - this.setNoIndex(true); - return this.void$; - }), + // Security: `doc.contents` is always authored by the documentation team + // and is considered to be safe. + tap(() => this.nextViewContainer.innerHTML = doc.contents || ''), + tap(() => swapOriginAndResult(this.nextViewContainer)), + tap(() => addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id)), + switchMap(() => this.elementsLoader.loadContainingCustomElements(this.nextViewContainer)), + tap(() => this.docReady.emit()) + , + switchMap(() => this.swapViews(addTitleAndToc)), + tap(() => this.docRendered.emit()), + catchError(err => { + const errorMessage = (err instanceof Error) ? err.stack : err; + this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`)); + this.nextViewContainer.innerHTML = ''; + this.setNoIndex(true); + return this.void$; + }), ); } @@ -174,7 +173,8 @@ export class DocViewerComponent implements OnDestroy { * entering animation has been completed. This is useful for work that needs to be done as soon as * the element has been attached to the DOM. */ - protected swapViews(onInsertedCb = () => {}): Observable { + protected swapViews(onInsertedCb = () => { + }): Observable { const raf$ = new Observable(subscriber => { const rafId = requestAnimationFrame(() => { subscriber.next(); @@ -192,26 +192,27 @@ export class DocViewerComponent implements OnDestroy { return 1000 * seconds; }; const animateProp = - (elem: HTMLElement, prop: keyof CSSStyleDeclaration, from: string, to: string, duration = 200) => { - const animationsDisabled = !DocViewerComponent.animationsEnabled - || this.hostElement.classList.contains(NO_ANIMATIONS); - if (prop === 'length' || prop === 'parentRule') { - // We cannot animate length or parentRule properties because they are readonly - return this.void$; - } - elem.style.transition = ''; - return animationsDisabled - ? this.void$.pipe(tap(() => elem.style[prop] = to)) - : this.void$.pipe( - // In order to ensure that the `from` value will be applied immediately (i.e. - // without transition) and that the `to` value will be affected by the - // `transition` style, we need to ensure an animation frame has passed between - // setting each style. - switchMap(() => raf$), tap(() => elem.style[prop] = from), - switchMap(() => raf$), tap(() => elem.style.transition = `all ${duration}ms ease-in-out`), - switchMap(() => raf$), tap(() => (elem.style as any)[prop] = to), - switchMap(() => timer(getActualDuration(elem))),switchMap(() => this.void$), - );}; + (elem: HTMLElement, prop: keyof CSSStyleDeclaration, from: string, to: string, duration = 200) => { + const animationsDisabled = !DocViewerComponent.animationsEnabled + || this.hostElement.classList.contains(NO_ANIMATIONS); + if (prop === 'length' || prop === 'parentRule') { + // We cannot animate length or parentRule properties because they are readonly + return this.void$; + } + elem.style.transition = ''; + return animationsDisabled + ? this.void$.pipe(tap(() => elem.style[prop] = to)) + : this.void$.pipe( + // In order to ensure that the `from` value will be applied immediately (i.e. + // without transition) and that the `to` value will be affected by the + // `transition` style, we need to ensure an animation frame has passed between + // setting each style. + switchMap(() => raf$), tap(() => elem.style[prop] = from), + switchMap(() => raf$), tap(() => elem.style.transition = `all ${duration}ms ease-in-out`), + switchMap(() => raf$), tap(() => (elem.style as any)[prop] = to), + switchMap(() => timer(getActualDuration(elem))), switchMap(() => this.void$), + ); + }; const animateLeave = (elem: HTMLElement) => animateProp(elem, 'opacity', '1', '0.1'); const animateEnter = (elem: HTMLElement) => animateProp(elem, 'opacity', '0.1', '1'); @@ -220,26 +221,26 @@ export class DocViewerComponent implements OnDestroy { if (this.currViewContainer.parentElement) { done$ = done$.pipe( - // Remove the current view from the viewer. - switchMap(() => animateLeave(this.currViewContainer)), - tap(() => this.currViewContainer.parentElement!.removeChild(this.currViewContainer)), - tap(() => this.docRemoved.emit()), + // Remove the current view from the viewer. + switchMap(() => animateLeave(this.currViewContainer)), + tap(() => this.currViewContainer.parentElement!.removeChild(this.currViewContainer)), + tap(() => this.docRemoved.emit()), ); } return done$.pipe( - // Insert the next view into the viewer. - tap(() => this.hostElement.appendChild(this.nextViewContainer)), - tap(() => onInsertedCb()), - tap(() => this.docInserted.emit()), - switchMap(() => animateEnter(this.nextViewContainer)), - // Update the view references and clean up unused nodes. - tap(() => { - const prevViewContainer = this.currViewContainer; - this.currViewContainer = this.nextViewContainer; - this.nextViewContainer = prevViewContainer; - this.nextViewContainer.innerHTML = ''; // Empty to release memory. - }), + // Insert the next view into the viewer. + tap(() => this.hostElement.appendChild(this.nextViewContainer)), + tap(() => onInsertedCb()), + tap(() => this.docInserted.emit()), + switchMap(() => animateEnter(this.nextViewContainer)), + // Update the view references and clean up unused nodes. + tap(() => { + const prevViewContainer = this.currViewContainer; + this.currViewContainer = this.nextViewContainer; + this.nextViewContainer = prevViewContainer; + this.nextViewContainer.innerHTML = ''; // Empty to release memory. + }), ); } diff --git a/aio/src/app/shared/toc.service.ts b/aio/src/app/shared/toc.service.ts index f1a40edb7d..7f08f9ee4e 100644 --- a/aio/src/app/shared/toc.service.ts +++ b/aio/src/app/shared/toc.service.ts @@ -1,9 +1,8 @@ import { DOCUMENT } from '@angular/common'; import { Inject, Injectable } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; -import { ReplaySubject } from 'rxjs'; import { ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-spy.service'; -import { ReplaySubject } from 'rxjs/ReplaySubject'; +import { ReplaySubject } from 'rxjs'; export interface TocItem {