因爲以前有幸去參加了ngChina2018開發者大會,聽了will保哥分享了Angular開發技巧,本身接觸Angular也有差很少快一年的時間了,因此打算對Angular開發中的一些技巧作一個整理。
所謂 「工欲善其事,必先利其器」,下面我會介紹 如何打磨 `VS Code` 這把利器
複製代碼
拋棄資源管理器
,使用快捷鍵 Commd + P
來查找文檔,默認會展現最近打開的文檔,而且支持模糊搜索文件node
快速打開最近文檔:前進 Ctrl+➕
後退 Ctrl+➖
git
靈活使用VS Code重構功能,能夠經過快捷鍵 Command +
對代碼進行重構瀏覽器
安裝插件 Angular Extension Pack
(認準will保哥出品),這個插件集成了不少提高Angular開發效率的插件,好比:bash
在 TS中實用 `ng-import-*` 導入常見的類
模板編輯的時候實用 ` a-*** ` 快速使用Angular的組件和指令 (Angular v7 Snippets)
實用 ` ng-* ` 來生成經常使用的ng代碼段,建立 Component,Directive 等 (Angular Snippets)
複製代碼
經過快捷鍵把JSON轉換成TS類async
Ctrl+Alt+V 把粘貼板中的JSON 轉爲 Typescript
Ctrl+Alt+S 將選中的JSON 生成對應的 Typescript
複製代碼
還有一個值得一提的一個比較實用的功能,經過快捷鍵來 快速切換組件對應的不一樣的文件
(Angular2-switcher)ide
還有不少其餘功能,插件中有詳細介紹 `Angular Extension Pack工具
安裝插件 Clipboard History
, 這個插件會存儲你最近的拷貝的記錄,方便記錄和粘貼最近幾回的拷貝內容性能
安裝插件 Local History
,這個插件用於維護文件的本地歷史記錄。每次修改文件時,舊內容的副本都會保留在本地歷史記錄中,你能夠隨時將文件與歷史記錄中的任何舊版本進行比較,若是發生意外時,能夠幫助咱們恢復丟失的內容,須要注意的是它會生成一個 .history
的文件夾進行本地修改的備份,因此咱們須要再 .gitignore
排除這個文件夾,避免將其提交到git倉儲。學習
安裝插件 Prettier - Code formatter
,這是一個代碼格式化的插件,用過幾個格式化的插件,我的感受最好用的一個,更適合Angular開發ui
安裝 Chrome 插件 Angular Angury
進行調試工做,能夠查看 Component 的 State,Router Tree,NgModules的一些狀態 (這個插件在複雜項目中並非特別好用,包括對一些動態組件的支持比較差,可是在一些簡單的項目中,或者新手在學習的時候安裝這個插件比較方便調試排錯)
下面會介紹一些Angular開發中的技巧
複製代碼
使用模板語言 as
, 使用 as 對一些嵌套結構深的屬性進行重命名
改進前:
<div *ngFor="let queue of fileUploadQueues">
<div class="icon" *ngIf="queue.result.file.icon">{{ queue.result.file.icon }}</div>
<div class="name" *ngIf="queue.result.file.name">{{ queue.result.file.name }}</div>
<div class="size" *ngIf="queue.result.file.size">{{ queue.result.file.size }}</div>
</div>
複製代碼
改進後:
<div *ngFor="let queue of fileUploadQueues">
<ng-container *ngIf="queue.result.file as file">
<div class="icon" *ngIf="file.icon">{{ file.icon }}</div>
<div class="name" *ngIf="file.name">{{ file.name }}</div>
<div class="size" *ngIf="file.size">{{ file.size }}</div>
</ng-container>
</div>
複製代碼
靈活使用 *ngIfElse
,不少人其實一直在寫*ngIf
並不知道其實Angular支持 else
的寫法 *ngIf="條件 ; else 模板"
,看看下面這兩段代碼
改進前:
<div *ngIf="(data$ | async).length > 0">
...
</div>
<div *ngIf="!(data$ | async).length > 0">
沒有數據
</div>
複製代碼
改進後:
<div *ngIf="(data$ | async).length > 0; else emptyTemplate;">
...
</div>
<ng-template #emptyTemplate>
沒有數據
</ng-template>
複製代碼
改進前的寫法,也能實現一樣的效果,可是由於數據是經過async
訂閱的,第一種寫法至關於進行了兩次訂閱,固然也能夠用 as 來解決,這裏只是一個示例。
還有一種狀況,在條件多的時候,經過第一種方式寫的話,若是條件有修改的話,必需要對取反後的條件進行維護, 而用 ngIfElse
的方式則只須要進行一次維護。
使用 ng-container
對代碼進行整理,使代碼更清晰,提高代碼的可讀性
<ng-container *ngIf="type === 1">
...
</ng-container>
<ng-container *ngIf="type === 2">
...
</ng-container>
<ng-container *ngIf="type === 3">
...
</ng-container>
複製代碼
@ViewChild
讀取指定類型的實例
<input #input thyInput [thyAutofocus]="true" />
複製代碼
上面這行代碼有三個實例 ElementRef
、ThyInputComponent
、ThyAutoFocusDirective
,在某些狀況下若是咱們要獲取指定類型的實例應該怎麼作呢?
@ViewChild('input', { read:ThyInputComponent }) inputComponent : ThyInputComponent ;
複製代碼
使用 async
管道,直接在模板中訂閱流,而沒必要將結果存儲在中間屬性中,當組件被銷燬時,Angular將會自動取消訂閱。
<div *ngFor="let item of data$ | async">
...
</div>
複製代碼
在一些狀況下,咱們可能須要重複使用訂閱的數據,可是咱們又不能每次使用的時候都用 async
去訂閱,因此咱們能夠經過剛纔說的 as
對齊進行重命名。
<div *ngFor="let item of data$ | async as data">
<span>一共有{{data.length}}條數據</span>
</div>
複製代碼
使用 takeUntil
來管理訂閱
在某些複雜的業務中,咱們可能須要訂閱多個流,一個一個去取消訂閱又繁瑣,又會產生不少冗餘代碼,不利於代碼的維護。這時候咱們能夠takeUntil
來管理多個訂閱,統一取消訂閱。
private _ngUnsubscribe$ = new Subject();
ngOnInit() {
this.students$.pipe(
takeUntil(_ngUnsubscribe$)
).subscribe(() => {
...
});
this.books$.pipe(
takeUntil(_ngUnsubscribe$)
).subscribe(() => {
...
});
}
ngOnDestroy() {
this._ngUnsubscribe$.next();
this._ngUnsubscribe$.complete();
}
複製代碼
合理使用 ngZone runOutsideAngular
來提高應用性能
咱們知道Angular能夠自動處理變化檢測,這是由於它使用了 zone.js
,簡單的來講,zone.js
就是經過打補丁的方式來攔截瀏覽器的事件,而後進行變化檢測,可是變化檢測是極其消耗資源的,若是綁定了大量的事件,那麼就會形成性能問題,因此咱們可使用 runOutsideAngular
來減小沒必要要的變化檢測。
this.ngZone.runOutsideAngular(() => {
this.renderer.listen(this.elementRef.nativeElement, 'keydown', event => {
const keyCode = event.which || event.keyCode;
if (keyCode === keycodes.ENTER) {
event.preventDefault();
this.ngZone.run(() => {
this.thyEnter.emit(event);
});
}
});
});
複製代碼
上面這段代碼是綁定一個回車事件,若是不使用 runOutsideAngular
的話,只要觸發鍵盤輸入事件,就會執行變化檢測,這時候咱們能夠用 runOutsideAngular
在只有爲enter事件的時候,去調用 ngZone.run()
主動觸發變化檢測
靈活使用 ngTemplateOutlet
來實現遞歸
<ng-container *ngFor="let node of treeNodes;" [ngTemplateOutlet]="nodeTemplate"
[ngTemplateOutletContext]="{node: node}">
</ng-container>
<ng-template #nodeTemplate let-node="node">
<div class='title'>{{node.title}}</div>
<ng-container *ngFor="let child of node?.children;" [ngTemplateOutlet]="nodeTemplate"
[ngTemplateOutletContext]="{node: child}">
</ng-container>
</ng-template>
複製代碼
在咱們實際開發的過程當中,常常會展現一些樹形結構的數據,若是業務場景比較簡單,能夠經過Angular的 ngTemplateOutlet
來實現遞歸展現,若是業務複雜,建議仍是經過組件的方式來實現。
上面是我這一年Angular開發的過程當中積累的一些小技巧(可能還有沒想起來的,我想起來會慢慢的往上補),你們若是發現有錯誤的地方,請指正。其實去年就寫好這篇文章,可是總感受缺點什麼,不過無所謂了~~ 但願能給Angular學習者提供幫助~
本文做者:王凱