记录一些 Angular v2+ 的贴士。常遇到的问题。

自我吐槽:Rxjs 学习曲线真陡啊。

以下内容未必对,参考参考。

001 - Observable、async pipe、rxjs

这段讲讲 rxjs 和 async pipe

分享 observable

https://gist.github.com/DrakeLeung/ecbcedab8534d4486a888ef777a76140#share

模版里面用了最新的 async pipe。 myData | async

async pipe 好处:它自动帮你订阅 Observable,还有 Component 在销毁时(onDestory)会自动取消订阅。

模版同样出现多个这样的语法时,Angular 默认会发出多次 HTTP Request 的。Angular 本身 HTTP 产生 “cold” Observable,跟 rxjs 本身一样。每个 subscription 都需要它自己的 Observable。

<p>{{ myData | async }} </p>

<div *ngFor="let d of myData | async">...</div>
// 平常的方法,Angular 就会发送多次 HTTP Request
getData(){
  this.myData = this._http
    .get('http://api.example.com/whatever')
    .map( (res:Response) => res.json() );
}
  

// 很简单,添加个 share 运算符就可以分享这个 Observable 了
getData() {
  this.myData = this._http
    .get('http://api.example.com/whatever')
    .map( (res:Response) => res.json() )
    .share(); // <--- 注意这个
}

Rxjs 也有长时间保存 Observable 的方法,请看这篇大师的文章(英文)。

注意的是,这种方法把 observable 变成 hot 模式。

视频解释:egghead (英文)

  • cold:xx网上面看视频,每个视频都有它独立的播放条,我看的不等于你看的。
  • hot:类似直播视频,大家(每个 subscriber)都能同步看到一样的东西。

用子元件

<user-detail [user]="myData | async"></user-detail>

子元件就可以用 @Input,这里你想怎么用都可以啦~。

没毛病,不过就多了子元件……😂

手动 "取消订阅"

每次 subscribe 时,加添到一个 var

在生命周期管理的 onDestory,再手动 unsubscribe(),这样就可以防止内存漏洞

this.subscription = blahlbha.subscribe(x => ...);

ngOnDestory() {
    this.subscription.unsubscribe();
}

从 observable 变成 promise

官方英文 Async Pipe 文档解释表达式可以是 observable 或者 promise。

所以我们可以这样:

this.myData = this.http.get('...')
                  .map(res => res.json())
                  .toPromise();

HTML 模版的语法可以保留用 myData | async 不变。这个方法不会产生多个 http request。

v4 中的新语法

模版里太多 someting$ | async 未免太乱了,Angular version 4 加入了新的 *ngIf 语法,下面这样:

<ng-template #loading>Loading...</ng-template>
<div *ngIf="userObservable | async; else loading; let user">
  {{ user.name }}
</div>

这个新的语法可以容易取代多个 (expression | async ) 这样,也可以不需要 Observable 的 .share() 。模版更加简洁一些。


002 - 安全导航运算符

https://angular.io/docs/ts/latest/guide/template-syntax.html#!#safe-navigation-operator

?. 这货叫做安全导航运算符(Safe Navigation Operator)。只要是 Object 基本都加上它吧。

作用:Object 是 undefined 就不会运行。

<p>Total: {{ (user | async)?.length }} </p>

<p>{{ (user | async)?.email }}</p>

003 - 结构型指令 <ng-container>

https://angular.io/docs/ts/latest/guide/structural-directives.html#!#ngcontainer

一些 div,span 可能会影响到 styling。某些位置不适合用任何 tag,可以用 <ng-container> 来代替。这个 ng-container 不会写进去 DOM,不会 render 出来。

<!-- my.component.html -->
<ng-container *ngIf="..."> blah blah blah <span>{{whatever}}</span></ng-container>

<!-- if true -->
blah blah blah <span>{{whatever}}</span>

004 - 分享服务

https://angular.cn/docs/ts/latest/guide/ngmodule.html#!#core-for-root

默认的情况下,模块都用自己的 DI(dependency injection)依赖注入。lazy load 的模块也是一样。简单来说,每个模块的依赖注入都是独立的。

一些服务(service)需求整个 app 使用分享一个状态(例如,登录状态),这时你就需要分享模组了,只需要添加一种静态方法(forRoot),在根模组 import 一次后,其它组建、模块不需要任何 import、DI 的情况下就能分享这些服务提供商了,可以包括 Angular 4 的 TitleService。