由於之前有幸去參加了ngChina2018開發者大會,聽了will保哥分享了Angular開發技巧,自己接觸Angular也有差不多快一年的時間了,所以打算對Angular開發中的一些技巧做一個整理
所謂 「工欲善其事,必先利其器」,下面我會介紹 如何打磨 `VS Code` 這把利器
資源管理器
Commd + P
2. 快速打開最近文檔:前進 Ctrl+? 後退 Ctrl+?
Ctrl+?
3. 靈活使用VS Code重構功能,可以通過快捷鍵 Command + 對代碼進行重構
Command +
4. 安裝插件 Angular Extension Pack (認準will保哥出品),這個插件集成了很多提升Angular開發效率的插件,比如:
Angular Extension Pack
在 TS中實用 ng-import-* 導入常見的類 模板編輯的時候實用 a-*** 快速使用Angular的組件和指令 (Angular v7 Snippets) 使用 ng-* 來生成常用的ng代碼段,創建 Component,Directive 等 (Angular Snippets)
通過快捷鍵把JSON轉換成TS類
Ctrl+Alt+V 把粘貼板中的JSON 轉為 Typescript Ctrl+Alt+S 將選中的JSON 生成對應的 Typescript
還有一個值得一提的一個比較實用的功能,通過快捷鍵來 快速切換組件對應的不同的文件 (Angular2-switcher)
還有很多其他功能,插件中有詳細介紹 `Angular Extension Pack
5. 安裝插件 Clipboard History , 這個插件會存儲你最近的拷貝的記錄,方便記錄和粘貼最近幾次的拷貝內容
Clipboard History
6. 安裝插件 Local History ,這個插件用於維護文件的本地歷史記錄。每次修改文件時,舊內容的副本都會保留在本地歷史記錄中,你可以隨時將文件與歷史記錄中的任何舊版本進行比較,如果發生意外時,可以幫助我們恢復丟失的內容,需要注意的是它會生成一個 .history 的文件夾進行本地修改的備份,所以我們需要再 .gitignore 排除這個文件夾,避免將其提交到git倉儲。
Local History
.history
.gitignore
7. 安裝插件 Prettier - Code formatter,這是一個代碼格式化的插件,用過幾個格式化的插件,個人感覺最好用的一個,更適合Angular開發
Prettier - Code formatter
8. 安裝 Chrome 插件 Angular Angury進行調試工作,可以查看 Component 的 State,Router Tree,NgModules的一些狀態 (這個插件在複雜項目中並不是特別好用,包括對一些動態組件的支持比較差,但是在一些簡單的項目中,或者新手在學習的時候安裝這個插件比較方便調試排錯)
Angular Angury
下面會介紹一些Angular開發中的技巧
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>
2. 靈活使用 *ngIfElse,很多人其實一直在寫*ngIf 並不知道其實Angular支持 else 的寫法 *ngIf="條件 ; else 模板;",看看下面這兩段代碼
*ngIfElse
*ngIf
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` 的方式則只需要進行一次維護。
3. 使用 ng-container 對代碼進行整理,使代碼更清晰,提升代碼的可讀性
ng-container
<ng-container *ngIf="type === 1"> ... </ng-container> <ng-container *ngIf="type === 2"> ... </ng-container> <ng-container *ngIf="type === 3"> ... </ng-container>
4. @ViewChild讀取指定類型的實例
@ViewChild
<input #input thyInput [thyAutofocus]="true" />
上面這行代碼有三個實例ElementRef、ThyInputComponent、ThyAutoFocusDirective,在某些情況下如果我們要獲取指定類型的實例應該怎麼做呢?
ElementRef
ThyInputComponent
ThyAutoFocusDirective
@ViewChild(input, { read:ThyInputComponent }) inputComponent : ThyInputComponent ;
5. 使用 async 管道,直接在模板中訂閱流,而不必將結果存儲在中間屬性中,當組件被銷毀時,Angular將會自動取消訂閱。
async
<div *ngFor="let item of data$ | async"> ... </div>
在一些情況下,我們可能需要重複使用訂閱的數據,但是我們又不能每次使用的時候都用 async 去訂閱,所以我們可以通過剛才說的 as 對其進行重命名。
<div *ngFor="let item of data$ | async as data"> <span>一共有{{data.length}}條數據</span> </div>
6. 使用 takeUntil 來管理訂閱 在某些複雜的業務中,我們可能需要訂閱多個流,一個一個去取消訂閱又繁瑣,又會產生很多冗餘代碼,不利於代碼的維護。這時候我們可以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(); }
7. 合理使用 ngZone runOutsideAngular 來提升應用性能 我們知道Angular可以自動處理變化檢測,這是因為它使用了 zone.js ,簡單的來說,zone.js 就是通過打補丁的方式來攔截瀏覽器的事件,然後進行變化檢測,但是變化檢測是極其消耗資源的,如果綁定了大量的事件,那麼就會造成性能問題,所以我們可以使用 runOutsideAngular 來減少不必要的變化檢測。
runOutsideAngular
zone.js
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() 主動觸發變化檢測。
ngZone.run()
8. 靈活使用 ngTemplateOutlet 來實現遞歸
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學習者提供幫助~
最後,感謝一下衣食父母,文章首發在Worktile官方博客,想了解更多關於產品設計、技術等方面的文章可前往查看。
TAG:Angular | RxJS |