2018 年 6 月

磁碟區 33 編號 6

本文章是由機器翻譯。

程式設計師雜談 - 如何使用 MEAN:反應式程式設計

Ted Neward |2018 年 6 月

歡迎回來,MEANers。

在先前的兩個發行項 (msdn.com/magazine/mt829391msdn.com/magazine/mt814413),我討論划算 Angular 所參照的內容為 「 範本驅動表單 」,也就是表單角度範本所描述,方法是使用程式碼,以控制驗證以及其他的邏輯擴充。這是不錯,但新的概念有關如何檢視 「 流程 」 的資訊 — 和結果的控制項出現在程式碼中 — 內 Web 應用程式正在啟動拿取 imaginations 開發人員。

我說話,當然的 「 互動式 」 程式設計,以及其中一個絕佳的排班 AngularJS (亦即,角度 1.0) 和 Angular 之間 (角度的 2.0 和更新版本),是 Angular 現在明確支援的程式設計,反應式樣式至少角度的層級。其中是說,Angular 支援而不必完全反應式風格的架構之外 Angular 認可使用反應靈敏 Angular 內進行程式設計的樣式。

我深入了解之前,不過,它可以協助確定所有人的上與 「 互動式 」 的意義這裡。

反應靈敏的反應

基本上,反應式樣式程式設計可輕鬆地了解,只要您願意完全反轉您的檢視方塊的 UI 程式設計的傳統方式。(是,這是在開玩笑。但只需小型的密碼)。

在建置 Ui 的傳統 MVC 為基礎的方法,會建立 UI 項目 (按鈕、 文字欄位等等),然後...您等待。在系統處理訊息從硬體,並結合的訊息,指出使用者做了什麼 — 已按一下按鈕,輸入到文字方塊中,或任何 — 程式碼的繫結至控制項引發。該程式碼通常會修改平放在 UI 中,後面的模型,並在應用程式會回到等候。

這種程式設計的 」 事件導向 」 樣式是在本質上是非同步,程式設計人員撰寫的程式碼永遠驅動的哪些使用者的動作。在某些方面,最好是呼叫 「 具決定性 」 程式設計,因為您曾無法知道哪些使用者將會執行下一步。角度要在其中搜尋要進行簡化建立雙向繫結之間的 UI 和資料模型,但仍然很難直接保留的項目順序。

反應靈敏的樣式,不過,採用更單向的方法。控制項建構在程式碼中 (而不是在範本中),且您以程式設計的方式訂閱發出回應使用者動作,這些控制項的事件。不是相當 React 樣式反應式程式設計中,已經相當接近,但它仍然允許相同類型之 「 不可變的資料模型 」 具有 enamored 產業的百分比表示的程式設計樣式。

反應式建構

若要開始,讓我們看看建構 SpeakerUI 元件,以被動方式,而不範本驅動的方式。(在這裡,我要進行更傳統的角度慣例,並為它 SpeakerDetail,但名稱並不重要的討論內容)。 首先,為了協助簡化功能正在使用中,我將使用的喇叭及 SpeakerService,簡短的形式中所示圖 1

圖 1 喇叭及 SpeakerService

import { Injectable } from '@angular/core';

export class Speaker {
  id = 0
  firstName = ""
  lastName = ""
  age = 0
}

@Injectable()
export class SpeakerService {
  private speakers : Speaker[] = [
    {
      id: 1,
      firstName: 'Brian',
      lastName: 'Randell',
      age: 47,
    },
    {
      id: 2,
      firstName: 'Ted',
      lastName: 'Neward',
      age: 46,
    },
    {
      id: 3,
      firstName: 'Rachel',
      lastName: 'Appel',
      age: 39,
    }
  ]
    getSpeakers() : Promise<Array<Speaker>> {
    return Promise.resolve(this.speakers);
  }
  getSpeaker(id: number) : Promise<Speaker> {
    return Promise.resolve(this.speakers[id - 1 ]);
  }
}

請注意 SpeakerService 使用 Promise.resolve 方法傳回的承諾,以立即解決。這是用來模擬服務而不必建置使用 Promise 建構函式的方式較長的承諾物件。

接下來,SpeakerDetail 元件只標準角度的元件 ("ng 新元件喇叭-詳細資料 」),並建構函式應該插入做為私用建構函式參數的 SpeakerService 執行個體。(這詳細我 2017 年 8 月資料行中,「 如何為平均:角度播放 Fetch"[msdn.com/magazine/mt826349]。) 當您在到達時,使用建構函式呼叫 SpeakerService getSpeakers 方法來取得陣列,並儲存,在本機至元件。 為屬性,稱為 「 喇叭。 」 為止,聽起來很像稍早所述的範本為基礎的元件。此元件的 HTML 範本將顯示在系統中 (由 getSpeakers),所有喇叭的下拉式清單,並為每個已選取,然後以另一組控制項下方的下拉式清單中顯示詳細資料。因此,範本如下所示圖 2

圖 2 HTML 範本

<h2>Select Speaker</h2>
<form [formGroup]="selectGroup">
<label>Speaker:
  <select formControlName="selectSpeaker">
    <option *ngFor="let speaker of speakers"
            [value]="speaker.lastName">{{speaker.lastName}}</option>
  </select>
</label>
</form>

<h2>Speaker Detail</h2>
<form [formGroup]="speakerForm" novalidate>
  <div>
    <label>First Name:
      <input formControlName="firstName">
    </label>
    <label>Last Name:
      <input formControlName="lastName">
    </label>
    <label>Age:
      <input formControlName="age">
    </label>
  </div>
</form>

它可能看起來很奇怪,另一個 「 以範本為基礎 」 的表單會使用 HTML 範本。這是主要是因為反應式表單方法還沒做什麼離開這個範本,但改為移除大部分遠離範本,且為元件的邏輯。這是其中項目會啟動,花費左轉從先前的資料行組中檢查的技術。元件的程式碼將會實際建構物件樹狀目錄控制項,並完全在程式碼基底內會發生這兩種形式中的控制項的大部分 (如果不是所有) 互動。我將不會將事件處理常式放在範本中。相反地,我會連結其內部元件的程式碼。

但首先,需要建構自己的控制項。這些將所有 FormControl 情況下,都是從 @angular/forms 模組匯入但它可以取得一點冗長來建構 (以及任何必要的驗證) 的每個以手動方式在程式碼中。幸運的是,Angular 提供 FormBuilder 類別是設計成讓事情更簡潔且具 compact 建構的控制項,特別是較長 (或巢狀) 表單的整個表單的價值。

在我的喇叭表單的情況下,我要有下拉式清單中,當做處理清單中選擇的喇叭的選取範圍機制 — 我需要採取稍微有點不同。我想要有兩種形式: 其中一個下拉式清單中的喇叭選取控制項,與另一個包含個別的喇叭的詳細資料。(通常這會是兩個不同的元件中的主版詳細資料種類的排列方式,但並未涵蓋尚未路由)。 因此,需要兩種形式,然後在圖 3我示範如何建構它們,同時 FormBuilder 逾時或無。

圖 3 建構表單

export class SpeakerDetailComponent implements OnInit {
  selectGroup : FormGroup
  speakerForm : FormGroup
  speakers : Speaker[]

  constructor(private formBuilder : FormBuilder,
              private speakerService : SpeakerService) {
    speakerService.getSpeakers().then( (res) => { this.speakers = res; });
    this.createForm();
  }

  createForm() {
    this.selectGroup = new FormGroup({
      selectSpeaker : new FormControl()
    });

    this.speakerForm = this.formBuilder.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      age: [0]
    });
  }
  // ...
}

這當然是,只有類別的摘錄,有一些事我需要新增之前已準備 「 出貨,但整齊這段程式碼會示範兩種方法來建構表單。「 SelectGroup 」 是包含一個 HTML < 選取 > 控制項,FormControl FormGroup 和使用 SpeakerService 填入本機演講者執行個體的陣列,讓 < 選取 > 可以填入本身。(這是實際的範本,不在元件的程式碼。如果沒有填入下拉式清單中,從元件的程式碼的方式,我已經中找不到它尚未角度 5。)

第二種形式,稱為 speakerForm,系統會填入使用 FormBuilder,也就是小小的 DSL 類似語言建構的控制項。請注意,我如何呼叫"group",表示我建構一整組控制項,這是有效的名稱 / 值組。名稱控制項 (它必須符合 formControlName 屬性中的每個控制項的範本) 的名稱,且值為一個初始值或初始值後面接著驗證函式 (兩個陣列,如果您想要加入驗證的陣列函式,以非同步方式執行) 來執行,以便驗證控制項中的值 」 的使用者類型。

這會建構兩種形式中,但下拉式清單中選取的項目不會執行任何動作。我需要回應的事件下拉式清單中將廣播,而且我可以執行此動作將連結的函式的 FormControl,"valueChanges"方法就像這樣:

export class SpeakerDetailComponent implements OnInit {
  // ...
  ngOnInit() {
    const speakerSelect = this.selectGroup.get('selectSpeaker');
    speakerSelect.valueChanges.forEach(
      (value:string) => {
        const speaker = this.speakers.find( (s) => s.lastName === value);
        this.populate(speaker);
      }
    );
  }
  // ...
}

請注意,valueChanges 屬性實際事件資料流。因此,我可以使用 forEach 來指示是透過每個事件,我想要採用的控制項變更 (lambda 的參數) 的值,然後使用它來傳回依據姓氏陣列中喇叭 SpeakerService 尋找。我然後將該演講者執行個體,並將它傳遞至填入方法,如下所示:

export class SpeakerDetailComponent implements OnInit {
  // ...
  populate(speaker) {
    const firstName = this.speakerForm.get('firstName');
    const lastName = this.speakerForm.get('lastName');
    const age = this.speakerForm.get('age');
    firstName.setValue(speaker.firstName);
    lastName.setValue(speaker.lastName);
    age.setValue(speaker.age);
  }
  // ...
}

填入方法只會抓取 FormControls 從 speakerForm] 群組中的參考,並使用 setValue 方法填入適當的控制項從喇叭的適當值。

反應式分析

公平詢問問題此時是如何這是比稍早所示的範本為基礎表單。老實說,它不是好的問題 — 它是不同的問題。(角度的文件甚至說此模型在官方文件頁面反應靈敏的表單上在 angular.io/guide/reactive-forms。) 擷取元件的程式碼中 (而不是在範本中) 的邏輯的大部分可能攻擊視為一個邏輯或凝聚力,有些開發人員,但反應式表單也會有它們基本上反應式 「 迴圈 」 的優點:因為控制項不直接對應至基礎模型物件。開發人員會保留完整的控制時,這可以簡化許多案例喜歡。

角度的小組不相信表單的其中一個方法是原本就是任何優於其他,事實上特別地陳述兩種樣式,可以使用相同的應用程式中。(不會嘗試使用同時在同一個元件,不過,除非您了解 Angular 真的太深。) 這裡的關鍵是 Angular 支援兩種不同的樣式,收集使用者輸入,兩者都是有效且可行的一定數量的案例。但是,如果您有大量的顯示,需要不同格式或需要顯示的格式取決於基礎模型物件,可以變更,會發生什麼事?角度提供另一個選項,您會看到下一個資料行中。祝各位寫程式愉快!


Ted Neward 是西雅圖 polytechnology 顧問、 喇叭和指導,目前正在處理的工程團隊以及開發人員逛-動作在主管為Smartsheet.com。他已寫入有大量的發行項,編寫或共置撰寫數十個活頁簿,並說出世界各地。連線到他處ted@tedneward.com或讀取在他的部落格blogs.tedneward.com