angular組件交互

1.父組件通過屬性綁定的方式將數(shù)組從上到下的流入到子組件中,子組件需要通過@Input裝飾器來獲取。

例如:

父組件為
@Component({
      template: `
          <ul class="list">
                 <li *ngFor="let contact of contacts">
                        <app-list-item [contact]="contact"></app-list-item>
                 </li>
          </ul>
`
})
export class ListComponent implement OnInit{
          this.contacts = data;
}
子組件為:
@Component({
        template:`
             <div class="contact-info">
                  <label class="contact-name">{{contact.name}}</label>
                  <label class="contact-tel">{{contact.telNum}}</label>
            </div>        
`
})
export class ListItemComponent implements OnInit{
      @Input() contact: any = {};
}
2.子組件通過事件傳遞的方式向父組件傳遞數(shù)據(jù),子組件需要實(shí)例化EventEmitter類,并使用裝飾器@Output修飾這個(gè)輸出屬性。父組件通過事件綁定的方式來訂閱來自子組件觸發(fā)的事件。
父組件:
@Component({
        template: `
            <contact-collect [contact]="detail" (onCollect)="collectTheContact($event)"></contact-collect>
        `
})
export class CollectionComponent implements OnInit{
        detail: any = {};
        collectTheContact(){
              this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;  
      }
}
父組件通過綁定自定義事件onCollect訂閱來自子組件觸發(fā)的事件。
子組件
@Component({
      template: `<i  (click)=collectionTheContact()>收藏</i>`
})
export class ContactCollectComponent{
      @Input() contact: any = {};
      @Output() onCollect = new EventEmitter<bollean>();
      collectTheContact(){
          this.onCollect.emit();
      }
}

通過@Output將數(shù)據(jù)流向父組件。

3.父組件通過局部變量獲取子組件的引用、父組件使用@ViewChild獲取子組件的引用

(1)在父組件的模板中為子組件創(chuàng)建一個(gè)局部變量,就可以在父組件的模板中訪問子組件的所有屬性和方法。這個(gè)局部變量有局限性,因?yàn)槟0遄兞恐荒茉谀0逯惺褂?,父組件的類不能使用這個(gè)局部變量訪問子組件的屬性和方法。
例如

父組件:
@Component({
      template:`
            <contact-collect (click)="collect.collectTheContact()" #collect></contact-collect>
      `
})
export class CollectionComponent{}
在父組件中為子組件創(chuàng)建了一個(gè)局部變量#collect,父組件就可以使用#collect調(diào)用子組件的方法collectTheContact()
子組件
@Component({
        template:<i>收藏</i>
})
export class ContactCollectComponent{
      detail: any = {};
      collectTheContact(){
          this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;
      }
}

(2)使用@ViewChid屬性裝飾器獲取子組件的引用,該方法獲取的引用可以在父組件類中使用。
@ViewChild()提供了一個(gè)參數(shù)來選擇將要引用的組件元素。這個(gè)參數(shù)可以是一個(gè)類的實(shí)例,也可以是字符串。
I.參數(shù)為類實(shí)例,表示父組件將綁定一個(gè)指令或者子組件實(shí)例
II.參數(shù)為字符串類型,相當(dāng)于在父組件中綁定一個(gè)模板局部變量,獲取到子組件的一個(gè)實(shí)例對(duì)象的引用。

參數(shù)為字符串
@ViewChild("dateRange")
private dateRange: OpsDateRangeComponent;
<ops-date-range #dateRange style="line-height: 29px"
                            (changeDateEvent)="dateListener($event)"></ops-date-range>
參數(shù)為類實(shí)例
@Component({
      template:`
            <contact-collect (click)="collectTheContact()"></contact-collect>
`
})
export class CollectionComponent{
      @ViewChild(ContactCollectComponent) contactCollect: ContactCollectComponent;
      ngAfterViewInit(){}
      collectTheContact(){
            this.contactCollect.collectTheContact();
      }
}
組件內(nèi)容嵌入

<ng-content>標(biāo)簽用來渲染組件嵌入內(nèi)容。
例如:

@Component({
    selector: 'example-content'
    template: `
        <div>
            <h4>ng-content實(shí)例</h4>
            <div style="background-color: gray">
                <ng-content select="header"></ng-content>
            </div>
       </div>
`
})
class NgContentExampleComponent{}
<ng-content>中有一個(gè)select="header",用于匹配內(nèi)容。并填充到ng-content中。
使用
@Component({
      selector:'app'
      template:`
          <example-content>
                <header>Header content</header>
          </exampe-content>
`
})
export class NgContentAppComponent{}
最后渲染成的是
<app>
    <example-content>
        <div>
            <h4>ng-content</h4>
            <div style="background-color: gray">
                <header>Header content</header>
            </div>
        </div>
       </example-content>
</app>
從圖中可以看出<header>Header content</header>被填充到了ng-content,select屬性是一個(gè)選擇器,類似于css的選擇器,可以有標(biāo)簽選擇器、類選擇器、屬性選擇器。

4.通過setter監(jiān)聽輸入屬性值的變化
使用一個(gè)輸入屬性的setter,來攔截父組件中值的變化,并采取行動(dòng)。

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-name-child',
  template: '<h3>"{{name}}"</h3>'
})
export class NameChildComponent {
  private _name = '';

  @Input()
  set name(name: string) {
    this._name = (name && name.trim()) || '<no name set>';
  }

  get name(): string { return this._name; }
}
在組件Namechildcomponent的輸入屬性name上設(shè)置了setter,會(huì)將父組件傳回來的name去掉空格,或者將空值替換成默認(rèn)的字符串。

5.通過ngOnChanges()來監(jiān)聽輸入屬性值的變化
使用OnChanges聲明周期鉤子接口的ngOnChanges()方法來監(jiān)測輸入屬性值的變化并做出回應(yīng)。(相比于setter方式,該方式可以艦艇多個(gè)輸入屬性)

import { Component, Input, OnChanges, SimpleChange } from '@angular/core';

@Component({
  selector: 'app-version-child',
  template: `
    <h3>Version {{major}}.{{minor}}</h3>
    <h4>Change log:</h4>
    <ul>
      <li *ngFor="let change of changeLog">{{change}}</li>
    </ul>
  `
})
export class VersionChildComponent implements OnChanges {
  @Input() major: number;
  @Input() minor: number;
  changeLog: string[] = [];

  ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
    let log: string[] = [];
    for (let propName in changes) {
      let changedProp = changes[propName];
      let to = JSON.stringify(changedProp.currentValue);
      if (changedProp.isFirstChange()) {
        log.push(`Initial value of ${propName} set to ${to}`);
      } else {
        let from = JSON.stringify(changedProp.previousValue);
        log.push(`${propName} changed from ${from} to ${to}`);
      }
    }
    this.changeLog.push(log.join(', '));
  }
}
這個(gè)VersionChildComponent 組件會(huì)監(jiān)測major和minor屬性的變化,并把這些變化寫成日志報(bào)告出來。
VersionChildComponent 提供minor和major值,把修改它們值的方法綁定到按鈕上。
import { Component } from '@angular/core';

@Component({
  selector: 'app-version-parent',
  template: `
    <h2>Source code version</h2>
    <button (click)="newMinor()">New minor version</button>
    <button (click)="newMajor()">New major version</button>
    <app-version-child [major]="major" [minor]="minor"></app-version-child>
  `
})
export class VersionParentComponent {
  major = 1;
  minor = 23;

  newMinor() {
    this.minor++;
  }

  newMajor() {
    this.major++;
    this.minor = 0;
  }
}

父組件和子組件通過服務(wù)來進(jìn)行通訊
父組件和子組件共享同一個(gè)服務(wù),利用該服務(wù)在組件家族中實(shí)現(xiàn)雙向通訊。
例如:
服務(wù):

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

@Injectable()
export class MissionService {

  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}

MissionControlComponent 提供服務(wù)的實(shí)例,并將其共享給它的子組件(通過 providers 元數(shù)據(jù)數(shù)組),子組件可以通過構(gòu)造函數(shù)將該實(shí)例注入到自身.

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

import { MissionService }     from './mission.service';

@Component({
  selector: 'app-mission-control',
  template: `
    <h2>Mission Control</h2>
    <button (click)="announce()">Announce mission</button>
    <app-astronaut *ngFor="let astronaut of astronauts"
      [astronaut]="astronaut">
    </app-astronaut>
    <h3>History</h3>
    <ul>
      <li *ngFor="let event of history">{{event}}</li>
    </ul>
  `,
  providers: [MissionService]
})
export class MissionControlComponent {
  astronauts = ['Lovell', 'Swigert', 'Haise'];
  history: string[] = [];
  missions = ['Fly to the moon!',
              'Fly to mars!',
              'Fly to Vegas!'];
  nextMission = 0;

  constructor(private missionService: MissionService) {
    missionService.missionConfirmed$.subscribe(
      astronaut => {
        this.history.push(`${astronaut} confirmed the mission`);
      });
  }

  announce() {
    let mission = this.missions[this.nextMission++];
    this.missionService.announceMission(mission);
    this.history.push(`Mission "${mission}" announced`);
    if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
  }
}

AstronautComponent 也通過自己的構(gòu)造函數(shù)注入該服務(wù)。由于每個(gè) AstronautComponent 都是 MissionControlComponent 的子組件,所以它們獲取到的也是父組件的這個(gè)服務(wù)實(shí)例。

import { Component, Input, OnDestroy } from '@angular/core';

import { MissionService } from './mission.service';
import { Subscription }   from 'rxjs';

@Component({
  selector: 'app-astronaut',
  template: `
    <p>
      {{astronaut}}: <strong>{{mission}}</strong>
      <button
        (click)="confirm()"
        [disabled]="!announced || confirmed">
        Confirm
      </button>
    </p>
  `
})
export class AstronautComponent implements OnDestroy {
  @Input() astronaut: string;
  mission = '<no mission announced>';
  confirmed = false;
  announced = false;
  subscription: Subscription;

  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnounced$.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }

  confirm() {
    this.confirmed = true;
    this.missionService.confirmMission(this.astronaut);
  }

  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.subscription.unsubscribe();
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 您將在本文當(dāng)中了解到,往網(wǎng)頁中添加數(shù)據(jù),從傳統(tǒng)的dom操作過渡到數(shù)據(jù)層操作,實(shí)現(xiàn)同一個(gè)目標(biāo),兩種不同的方式....
    itclanCoder閱讀 25,915評(píng)論 1 12
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 2,860評(píng)論 2 9
  • 組件基礎(chǔ) 組件用來包裝特定的功能,應(yīng)用程序的有序運(yùn)行依賴于組件之間的協(xié)同工作。組件是angular應(yīng)用的最小邏輯單...
    oWSQo閱讀 1,396評(píng)論 0 0
  • 最近到了新公司,用的技術(shù)是angular4,以前只用過angular1,本來以為兩者差別不大,結(jié)果了解之后才知道...
    小燕子小圓子閱讀 331評(píng)論 1 3
  • 我出生在那個(gè)小山村,那里的人們淳樸善良。 不記事時(shí),爸爸便去了外地工作,常年不在家。偶爾回家,我都不認(rèn)識(shí),只認(rèn)得那...
    憶雪兒閱讀 418評(píng)論 2 3