fix: merge code & fix some issues
This commit is contained in:
parent
8136953a09
commit
f7a6ccbb5d
@ -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
|
The rest of the class has been rewritten to expose a `getHeroes` method
|
||||||
that returns the same mock data as before.
|
that returns the same mock data as before.
|
||||||
|
|
||||||
[`@Injectable` 装饰器](#injectable)是定义每个 Angular 服务时的必备部分。
|
`@Injectable` 装饰器是定义每个 Angular 服务时的必备部分。
|
||||||
把该类的其它部分改写为暴露一个返回和以前一样的 mock 数据的 `getHeroes` 方法。
|
把该类的其它部分改写为暴露一个返回和以前一样的 mock 数据的 `getHeroes` 方法。
|
||||||
|
|
||||||
<code-example path="dependency-injection/src/app/heroes/hero.service.3.ts" title="src/app/heroes/hero.service.3.ts">
|
<code-example path="dependency-injection/src/app/heroes/hero.service.3.ts" title="src/app/heroes/hero.service.3.ts">
|
||||||
|
@ -7,56 +7,31 @@ Angular is a platform that makes it easy to build applications with the web. Ang
|
|||||||
Angular 是一个开发平台。它能帮你更轻松的构建 Web 应用。Angular 集声明式模板、依赖注入、端到端工具和一些最佳实践于一身,为你解决开发方面的各种挑战。Angular 为开发者提升构建 Web、手机或桌面应用的能力。
|
Angular 是一个开发平台。它能帮你更轻松的构建 Web 应用。Angular 集声明式模板、依赖注入、端到端工具和一些最佳实践于一身,为你解决开发方面的各种挑战。Angular 为开发者提升构建 Web、手机或桌面应用的能力。
|
||||||
|
|
||||||
<div class="card-container">
|
<div class="card-container">
|
||||||
|
|
||||||
<a href="generated/live-examples/toh-pt1/stackblitz.html" target="_blank" class="docs-card"
|
<a href="generated/live-examples/toh-pt1/stackblitz.html" target="_blank" class="docs-card"
|
||||||
title="Experience Angular in a live coding environment">
|
title="Experience Angular in a live coding environment">
|
||||||
|
|
||||||
<section>Get a Glimpse of Angular</section>
|
<section>Get a Glimpse of Angular</section>
|
||||||
|
|
||||||
<section>Angular 走马观花</section>
|
<section>Angular 走马观花</section>
|
||||||
|
|
||||||
<p>A quick look at an Angular "hello world" application.</p>
|
<p>A quick look at an Angular "hello world" application.</p>
|
||||||
|
|
||||||
<p>快速体验 Angular 的 "hello world" 应用。</p>
|
<p>快速体验 Angular 的 "hello world" 应用。</p>
|
||||||
|
|
||||||
<p class="card-footer">Angular in Action</p>
|
<p class="card-footer">Angular in Action</p>
|
||||||
|
|
||||||
<p class="card-footer">体验 Angular</p>
|
<p class="card-footer">体验 Angular</p>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="guide/quickstart" class="docs-card" title="Angular Quickstart">
|
<a href="guide/quickstart" class="docs-card" title="Angular Quickstart">
|
||||||
|
|
||||||
<section>Get Going with Angular</section>
|
<section>Get Going with Angular</section>
|
||||||
|
|
||||||
<section>开始使用 Angular</section>
|
<section>开始使用 Angular</section>
|
||||||
|
|
||||||
<p>Get going on your own environment with the Quickstart.</p>
|
<p>Get going on your own environment with the Quickstart.</p>
|
||||||
|
|
||||||
<p>跟随"快速上手"构建你的开发环境</p>
|
<p>跟随"快速上手"构建你的开发环境</p>
|
||||||
|
|
||||||
<p class="card-footer">Quickstart</p>
|
<p class="card-footer">Quickstart</p>
|
||||||
|
|
||||||
<p class="card-footer">快速上手</p>
|
<p class="card-footer">快速上手</p>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="guide/architecture" class="docs-card" title="Angular Architecture">
|
<a href="guide/architecture" class="docs-card" title="Angular Architecture">
|
||||||
|
|
||||||
<section>Fundamentals</section>
|
<section>Fundamentals</section>
|
||||||
|
|
||||||
<section>基本原理</section>
|
<section>基本原理</section>
|
||||||
|
|
||||||
<p>Learn Angular application fundamentals, starting with an architecture overview.</p>
|
<p>Learn Angular application fundamentals, starting with an architecture overview.</p>
|
||||||
|
|
||||||
<p>学习 Angular 应用的基本原理。<br/>从架构概览开始。</p>
|
<p>学习 Angular 应用的基本原理。<br/>从架构概览开始。</p>
|
||||||
|
|
||||||
<p class="card-footer">Architecture</p>
|
<p class="card-footer">Architecture</p>
|
||||||
|
|
||||||
<p class="card-footer">架构</p>
|
<p class="card-footer">架构</p>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Assumptions
|
## 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,
|
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.
|
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://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
|
## Feedback
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import { AsyncSubject, Observable, of } from 'rxjs';
|
|||||||
import { catchError, switchMap, tap } from 'rxjs/operators';
|
import { catchError, switchMap, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { DocumentContents } from './document-contents';
|
import { DocumentContents } from './document-contents';
|
||||||
|
import { Logger } from '../shared/logger.service';
|
||||||
|
import { LocationService } from '../shared/location.service';
|
||||||
|
|
||||||
export { DocumentContents } from './document-contents';
|
export { DocumentContents } from './document-contents';
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { Component, ElementRef, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
|
import { Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy, Output } from '@angular/core';
|
||||||
import { HostListener } from '@angular/core';
|
import { Meta, Title } from '@angular/platform-browser';
|
||||||
import { Title, Meta } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { Observable, of, timer } from 'rxjs';
|
import { Observable, of, timer } from 'rxjs';
|
||||||
import { catchError, switchMap, takeUntil, tap } from 'rxjs/operators';
|
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 { Logger } from 'app/shared/logger.service';
|
||||||
import { TocService } from 'app/shared/toc.service';
|
import { TocService } from 'app/shared/toc.service';
|
||||||
import { ElementsLoader } from 'app/custom-elements/elements-loader';
|
import { ElementsLoader } from 'app/custom-elements/elements-loader';
|
||||||
@ -79,10 +78,10 @@ export class DocViewerComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.docContents$
|
this.docContents$
|
||||||
.pipe(switchMap(newDoc => this.render(newDoc)),
|
.pipe(switchMap(newDoc => this.render(newDoc)),
|
||||||
takeUntil(this.onDestroy$),
|
takeUntil(this.onDestroy$),
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@ -133,23 +132,23 @@ export class DocViewerComponent implements OnDestroy {
|
|||||||
this.setNoIndex(doc.id === FILE_NOT_FOUND_ID || doc.id === FETCHING_ERROR_ID);
|
this.setNoIndex(doc.id === FILE_NOT_FOUND_ID || doc.id === FETCHING_ERROR_ID);
|
||||||
|
|
||||||
return this.void$.pipe(
|
return this.void$.pipe(
|
||||||
// Security: `doc.contents` is always authored by the documentation team
|
// Security: `doc.contents` is always authored by the documentation team
|
||||||
// and is considered to be safe.
|
// and is considered to be safe.
|
||||||
tap(() => this.nextViewContainer.innerHTML = doc.contents || ''),
|
tap(() => this.nextViewContainer.innerHTML = doc.contents || ''),
|
||||||
tap(() => swapOriginAndResult(this.nextViewContainer))
|
tap(() => swapOriginAndResult(this.nextViewContainer)),
|
||||||
.do(() =>addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id)),
|
tap(() => addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id)),
|
||||||
switchMap(() => this.elementsLoader.loadContainingCustomElements(this.nextViewContainer)),
|
switchMap(() => this.elementsLoader.loadContainingCustomElements(this.nextViewContainer)),
|
||||||
tap(() => this.docReady.emit())
|
tap(() => this.docReady.emit())
|
||||||
,
|
,
|
||||||
switchMap(() => this.swapViews(addTitleAndToc)),
|
switchMap(() => this.swapViews(addTitleAndToc)),
|
||||||
tap(() => this.docRendered.emit()),
|
tap(() => this.docRendered.emit()),
|
||||||
catchError(err => {
|
catchError(err => {
|
||||||
const errorMessage = (err instanceof Error) ? err.stack : err;
|
const errorMessage = (err instanceof Error) ? err.stack : err;
|
||||||
this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`));
|
this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`));
|
||||||
this.nextViewContainer.innerHTML = '';
|
this.nextViewContainer.innerHTML = '';
|
||||||
this.setNoIndex(true);
|
this.setNoIndex(true);
|
||||||
return this.void$;
|
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
|
* 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.
|
* the element has been attached to the DOM.
|
||||||
*/
|
*/
|
||||||
protected swapViews(onInsertedCb = () => {}): Observable<void> {
|
protected swapViews(onInsertedCb = () => {
|
||||||
|
}): Observable<void> {
|
||||||
const raf$ = new Observable<void>(subscriber => {
|
const raf$ = new Observable<void>(subscriber => {
|
||||||
const rafId = requestAnimationFrame(() => {
|
const rafId = requestAnimationFrame(() => {
|
||||||
subscriber.next();
|
subscriber.next();
|
||||||
@ -192,26 +192,27 @@ export class DocViewerComponent implements OnDestroy {
|
|||||||
return 1000 * seconds;
|
return 1000 * seconds;
|
||||||
};
|
};
|
||||||
const animateProp =
|
const animateProp =
|
||||||
(elem: HTMLElement, prop: keyof CSSStyleDeclaration, from: string, to: string, duration = 200) => {
|
(elem: HTMLElement, prop: keyof CSSStyleDeclaration, from: string, to: string, duration = 200) => {
|
||||||
const animationsDisabled = !DocViewerComponent.animationsEnabled
|
const animationsDisabled = !DocViewerComponent.animationsEnabled
|
||||||
|| this.hostElement.classList.contains(NO_ANIMATIONS);
|
|| this.hostElement.classList.contains(NO_ANIMATIONS);
|
||||||
if (prop === 'length' || prop === 'parentRule') {
|
if (prop === 'length' || prop === 'parentRule') {
|
||||||
// We cannot animate length or parentRule properties because they are readonly
|
// We cannot animate length or parentRule properties because they are readonly
|
||||||
return this.void$;
|
return this.void$;
|
||||||
}
|
}
|
||||||
elem.style.transition = '';
|
elem.style.transition = '';
|
||||||
return animationsDisabled
|
return animationsDisabled
|
||||||
? this.void$.pipe(tap(() => elem.style[prop] = to))
|
? this.void$.pipe(tap(() => elem.style[prop] = to))
|
||||||
: this.void$.pipe(
|
: this.void$.pipe(
|
||||||
// In order to ensure that the `from` value will be applied immediately (i.e.
|
// 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
|
// without transition) and that the `to` value will be affected by the
|
||||||
// `transition` style, we need to ensure an animation frame has passed between
|
// `transition` style, we need to ensure an animation frame has passed between
|
||||||
// setting each style.
|
// setting each style.
|
||||||
switchMap(() => raf$), tap(() => elem.style[prop] = from),
|
switchMap(() => raf$), tap(() => elem.style[prop] = from),
|
||||||
switchMap(() => raf$), tap(() => elem.style.transition = `all ${duration}ms ease-in-out`),
|
switchMap(() => raf$), tap(() => elem.style.transition = `all ${duration}ms ease-in-out`),
|
||||||
switchMap(() => raf$), tap(() => (elem.style as any)[prop] = to),
|
switchMap(() => raf$), tap(() => (elem.style as any)[prop] = to),
|
||||||
switchMap(() => timer(getActualDuration(elem))),switchMap(() => this.void$),
|
switchMap(() => timer(getActualDuration(elem))), switchMap(() => this.void$),
|
||||||
);};
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const animateLeave = (elem: HTMLElement) => animateProp(elem, 'opacity', '1', '0.1');
|
const animateLeave = (elem: HTMLElement) => animateProp(elem, 'opacity', '1', '0.1');
|
||||||
const animateEnter = (elem: HTMLElement) => animateProp(elem, 'opacity', '0.1', '1');
|
const animateEnter = (elem: HTMLElement) => animateProp(elem, 'opacity', '0.1', '1');
|
||||||
@ -220,26 +221,26 @@ export class DocViewerComponent implements OnDestroy {
|
|||||||
|
|
||||||
if (this.currViewContainer.parentElement) {
|
if (this.currViewContainer.parentElement) {
|
||||||
done$ = done$.pipe(
|
done$ = done$.pipe(
|
||||||
// Remove the current view from the viewer.
|
// Remove the current view from the viewer.
|
||||||
switchMap(() => animateLeave(this.currViewContainer)),
|
switchMap(() => animateLeave(this.currViewContainer)),
|
||||||
tap(() => this.currViewContainer.parentElement!.removeChild(this.currViewContainer)),
|
tap(() => this.currViewContainer.parentElement!.removeChild(this.currViewContainer)),
|
||||||
tap(() => this.docRemoved.emit()),
|
tap(() => this.docRemoved.emit()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return done$.pipe(
|
return done$.pipe(
|
||||||
// Insert the next view into the viewer.
|
// Insert the next view into the viewer.
|
||||||
tap(() => this.hostElement.appendChild(this.nextViewContainer)),
|
tap(() => this.hostElement.appendChild(this.nextViewContainer)),
|
||||||
tap(() => onInsertedCb()),
|
tap(() => onInsertedCb()),
|
||||||
tap(() => this.docInserted.emit()),
|
tap(() => this.docInserted.emit()),
|
||||||
switchMap(() => animateEnter(this.nextViewContainer)),
|
switchMap(() => animateEnter(this.nextViewContainer)),
|
||||||
// Update the view references and clean up unused nodes.
|
// Update the view references and clean up unused nodes.
|
||||||
tap(() => {
|
tap(() => {
|
||||||
const prevViewContainer = this.currViewContainer;
|
const prevViewContainer = this.currViewContainer;
|
||||||
this.currViewContainer = this.nextViewContainer;
|
this.currViewContainer = this.nextViewContainer;
|
||||||
this.nextViewContainer = prevViewContainer;
|
this.nextViewContainer = prevViewContainer;
|
||||||
this.nextViewContainer.innerHTML = ''; // Empty to release memory.
|
this.nextViewContainer.innerHTML = ''; // Empty to release memory.
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { DOCUMENT } from '@angular/common';
|
import { DOCUMENT } from '@angular/common';
|
||||||
import { Inject, Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||||
import { ReplaySubject } from 'rxjs';
|
|
||||||
import { ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-spy.service';
|
import { ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-spy.service';
|
||||||
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
import { ReplaySubject } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
export interface TocItem {
|
export interface TocItem {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user