Angular 學習筆記 (組件溝通的思考)

組件指令間常常須要溝通 git

咱們知道的方式有 github

input編程

outputapi

servicethis

injectspa

viewchildcode

contentchildcomponent

templateReform

template variable對象

可是哪一種狀況下用哪一種呢 ? 

 

思考 1, input -> input -> input 這種一層層傳進去是不是 ok 的 ? 

<mat-calendar cdkTrapFocus
    [id]="datepicker.id"
    [ngClass]="datepicker.panelClass"
    [startAt]="datepicker.startAt"
    [startView]="datepicker.startView"
    [minDate]="datepicker._minDate"
    [maxDate]="datepicker._maxDate"
    [dateFilter]="datepicker._dateFilter"
    [headerComponent]="datepicker.calendarHeaderComponent"
    [selected]="datepicker._selected"
    [dateClass]="datepicker.dateClass"
    [@fadeInCalendar]="'enter'"
    (selectedChange)="datepicker.select($event)"
    (yearSelected)="datepicker._selectYear($event)"
    (monthSelected)="datepicker._selectMonth($event)"
    (_userSelection)="datepicker.close()">
</mat-calendar>

看看人家 material datepicker 

datepicker 指令經過 overlay 建立 datepickerContent 組件, 而後 this._popupComponentRef.instance.datepicker = this; 把本身傳進去, 在把 datepicker input 一個個放入 mat-calendar input (上圖)

  private _openAsPopup(): void {
    if (!this._calendarPortal) {
      this._calendarPortal = new ComponentPortal<MatDatepickerContent<D>>(MatDatepickerContent,
                                                                          this._viewContainerRef);
    }

    if (!this._popupRef) {
      this._createPopup();
    }

    if (!this._popupRef.hasAttached()) {
      this._popupComponentRef = this._popupRef.attach(this._calendarPortal);
      this._popupComponentRef.instance.datepicker = this;
      this._setColor();

      // Update the position once the calendar has rendered.
      this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(() => {
        this._popupRef.updatePosition();
      });
    }
  }

因此你說 input -> input 又如何呢 ?

我我的以爲 wrap component 就一層一層傳咯, 無所謂的啦. 

 

思考 2 : output vs input callback function 

<abc (submit)="submit($event)" [submitFn]="submitFn"  ></abc>

output 是廣播的概念, 廣播的缺點就是沒有的寫 callback, 

假設我想封裝一個 submit loading, submit 由外部負責, 那麼我寫一個 output 我就沒法知道何時 loading 結束, 除非外部又 input 一個 submit 結束進來. 

若是是 input + callback 就容易. 

可是 input + callback 也有問題就是不能任意輸入變量

好比 (submit)="submit($event, index)" 能夠很簡單的傳入 ngFor 的 index, 而 submitFn 就不行了.

廣播後有一種方式能夠跟外部溝通就是經過 event 

好比 event.preventDefault() 就是一個通信. 

咱們能夠作一個 event.submitDone() 來通知內部, submit 結束了,讓 loading 關閉. 

可是這種方式仍是有點詭異, 畢竟廣播的概念是能夠多我的監聽. 這個 submitDone 視乎指定了一個監聽者在使用.. 

最後我也不知道如何是好啦. 

 

思考 3 : ng-content vs input ng-template 

content 很直觀, 可是缺點也很恐怖, 就是隻能一層. 你 wrap 一個 component 基本上 content 就廢了.

怎麼說廢了呢, 由於 contentchild 會獲取不了 

https://github.com/angular/angular/issues/20810

https://github.com/angular/angular/issues/8563

看看 material table 

https://github.com/angular/material2/issues/6980

若是你 wrap 了 material table, 你須要經過 viewchild 找到 mat table 而後調用 api 來把 content 輸入進去. 是否是麻煩 ? 

對比 ng-template 或者 dynamic component 就不一樣了. 經過 input 輸入, 就能夠傳到底層, 好比 material datepicker 的 header component.

此外它們還有很大的不一樣在於使用.

看看 material select , material option group , material option 的配搭. 

若是用 template 實現就很不一樣了. 

這個例子中 option 是外部負責 ngfor 建立而後傳入的, template 要實現的話. 你只能傳入 items + template 內部實現 ngfor 渲染 template.

 

思考 4:  template variable 

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let option of options" [value]="option">
        {{option}}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

注意 mat-autocomplete 和 input 是如何連上的嗎 ? 

經過一個指令 [matAutocomplete] + template variable 

若是你熟悉面向對象編程, 而後把 component 想象成 new ComponentClass 獲得的對象.

那麼你會發現模板之間就是 對象與對象的互相方法調用,修改屬性而已. 

因此當你 new 了不少 component 後,你要他們一塊兒工做,你就須要讓它們互相依賴. 

好比 

let input = new Input();

let autoDir = new AutoDir();

let auto = new Auto();

autoDir.auto = auto;

autoDir.input = input;

autoDir.watchInputThenOpenAuto();

watchInputThenOpenAuto(){ 

  this.input.change(() => {  this.auto.open().filterBy(this.input.value);  });

}

相關文章
相關標籤/搜索