记录一些 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 - 结构型指令 #
https://angular.io/docs/ts/latest/guide/structural-directives.html#!#ngcontainer
一些 div,span 可能会影响到 styling。某些位置不适合用任何 tag,可以用
<!-- 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。