Angular開發技巧

因爲以前有幸去參加了ngChina2018開發者大會,聽了will保哥分享了Angular開發技巧,本身接觸Angular也有差很少快一年的時間了,因此打算對Angular開發中的一些技巧作一個整理。

工具篇

所謂 「工欲善其事,必先利其器」,下面我會介紹 如何打磨 `VS Code` 這把利器
複製代碼
  1. 拋棄資源管理器 ,使用快捷鍵 Commd + P 來查找文檔,默認會展現最近打開的文檔,而且支持模糊搜索文件node

    222.png

  2. 快速打開最近文檔:前進 Ctrl+➕ 後退 Ctrl+➖git

  3. 靈活使用VS Code重構功能,能夠經過快捷鍵 Command + 對代碼進行重構瀏覽器

    333.png

  4. 安裝插件 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

    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開發ui

  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技術博客

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

文章轉載請註明出處。

相關文章
相關標籤/搜索