Angular開發技巧

wow_worktile發表於2019-03-06
由於之前有幸去參加了ngChina2018開發者大會,聽了will保哥分享了Angular開發技巧,自己接觸Angular也有差不多快一年的時間了,所以打算對Angular開發中的一些技巧做一個整理。

工具篇

所謂 “工欲善其事,必先利其器”,下面我會介紹 如何打磨 `VS Code` 這把利器
複製程式碼
  1. 拋棄資源管理器 ,使用快捷鍵 Commd + P 來查詢文件,預設會展示最近開啟的文件,並且支援模糊搜尋檔案

    222.png

  2. 快速開啟最近文件:前進 Ctrl+➕ 後退 Ctrl+➖

  3. 靈活使用VS Code重構功能,可以通過快捷鍵 Command + 對程式碼進行重構

    333.png

  4. 安裝外掛 Angular Extension Pack (認準will保哥出品),這個外掛整合了很多提升Angular開發效率的外掛,比如:

    在 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)

    e5dc25f8-a0ec-4706-919a-aa19194a7017.png

    還有很多其他功能,外掛中有詳細介紹 `Angular Extension Pack

  5. 安裝外掛 Clipboard History , 這個外掛會儲存你最近的拷貝的記錄,方便記錄和貼上最近幾次的拷貝內容

    111.png

  6. 安裝外掛 Local History ,這個外掛用於維護檔案的本地歷史記錄。每次修改檔案時,舊內容的副本都會保留在本地歷史記錄中,你可以隨時將檔案與歷史記錄中的任何舊版本進行比較,如果發生意外時,可以幫助我們恢復丟失的內容,需要注意的是它會生成一個 .history 的資料夾進行本地修改的備份,所以我們需要再 .gitignore 排除這個資料夾,避免將其提交到git倉儲。

  7. 安裝外掛 Prettier - Code formatter,這是一個程式碼格式化的外掛,用過幾個格式化的外掛,個人感覺最好用的一個,更適合Angular開發

  8. 安裝 Chrome 外掛 Angular Angury進行除錯工作,可以檢視 Component 的 State,Router Tree,NgModules的一些狀態 (這個外掛在複雜專案中並不是特別好用,包括對一些動態元件的支援比較差,但是在一些簡單的專案中,或者新手在學習的時候安裝這個外掛比較方便除錯排錯)

    444.png

    555.png

開發篇

下面會介紹一些Angular開發中的技巧
複製程式碼
  1. 使用模板語言 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>
    複製程式碼
  2. 靈活使用 *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 的方式則只需要進行一次維護。

  3. 使用 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 讀取指定型別的例項

    <input #input thyInput  [thyAutofocus]="true" />
    複製程式碼

    上面這行程式碼有三個例項 ElementRefThyInputComponentThyAutoFocusDirective,在某些情況下如果我們要獲取指定型別的例項應該怎麼做呢?

    @ViewChild('input', { read:ThyInputComponent })  inputComponent : ThyInputComponent ;
    複製程式碼
  5. 使用 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>
    複製程式碼
  6. 使用 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 來減少不必要的變化檢測。

    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() 主動觸發變化檢測

  8. 靈活使用 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技術部落格

歡迎訪問交流更多關於技術及協作的問題。

文章轉載請註明出處。


相關文章