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);  });

}

相关文章
相关标签/搜索