網站搜尋

typescript - Angular 2 @Input:是否可以將資料從一個元件傳遞到另一個子路由元件?


根據 Angular 2 的文件,你可以很容易地使用 @Input 從一個組件傳遞資料到另一個組件。

例如,我可以這樣設置父物件:

import { Component } from '@angular/core';
import { HEROES } from './hero';
@Component({
  selector: 'hero-parent',
  template: `
    <h2>{{master}} controls {{heroes.length}} heroes</h2>
    <hero-child *ngFor="let hero of heroes"
      [hero]="hero"
      [master]="master">
    </hero-child>
  `
})
export class HeroParentComponent {
  heroes = HEROES;
  master: string = 'Master';
}

然後在子組件中這樣獲取數據:

import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
  selector: 'hero-child',
  template: `
    <h3>{{hero.name}} says:</h3>
    <p>I, {{hero.name}}, am at your service, {{masterName}}.</p>
  `
})
export class HeroChildComponent {
  @Input() hero: Hero;
  @Input('master') masterName: string;
}

所以這很明顯,把 [hero]="data" 傳遞給父組件的模板(當然在子選擇器中)並在子組件中處理它們。

但問題在這裡。

我的子元件 DOM 元素(在此例中為 <hero-child>)在父元件的模板中不可用,而是透過 <router-outlet> 元素在那裡載入。

那麼我該如何將資料傳給子路由組件呢?輸入屬性不是正確的方式嗎?我想避免對已經在父路由/組件中擁有的相同資料進行二次、三次等多次呼叫。

答案#1

我不相信有任何方法可以將物件作為輸入傳遞給被路由的組件。我是使用一個帶有可觀察對象的服務來在父組件和一個或多個子組件之間共享數據來實現這一點的。

基本上,父元件會呼叫服務並將它所需的任何資料傳給服務。在我的例子中只是傳送一個 ID,但它可以是任何東西。然後服務可以對這些資料做一些處理(或不做)。在我的示例中,我是根據 ID 向伺服器發出請求以獲取公司資料,但如果你已經有了所需的物件,這步驟就不需要。然後它會將一個物件推送到一個 Observable 流中,該流在子元件中被訂閱。

父元件:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { SalesProcessService } from './salesProcess.service';
import { Subscription } from 'rxjs/Rx';

@Component({
    selector: 'ex-sales-process',
    template: `
        <router-outlet></router-outlet>
    `
})
export class SalesProcessComponent implements OnInit, OnDestroy {
    private companyRowId: string;
    private paramsSubscription: Subscription;
    constructor(
        private salesProcessService: SalesProcessService,
        private route: ActivatedRoute
    ) {}
    ngOnInit() {
        this.paramsSubscription = this.route.params.subscribe((params: Params) => {
            if (this.companyRowId !== params['companyId']) {
                this.companyRowId = params['companyId'];
                this.salesProcessService.getCompany(this.companyRowId);
            }
        });
    }
    ngOnDestroy() {
        this.paramsSubscription.unsubscribe();
    }

}

服務:

import { Injectable } from '@angular/core';
import { CompanyDataService } from '../common/services/data';
import { ReplaySubject } from 'rxjs';
import { Observable, Subject, Subscription } from 'rxjs/Rx';

@Injectable()
export class SalesProcessService {
    private companyLoadedSource = new ReplaySubject<any>(1);
    /* tslint:disable:member-ordering */
    companyLoaded$ = this.companyLoadedSource.asObservable();
    /* tslint:enable:member-ordering */

    constructor (
        private companyDataService: CompanyDataService) { }
    getCompany(companyRowId: string) {
      // Data service that makes http call and returns Observable
        this.companyDataService.getCompany(companyRowId).subscribe(company => this.companyLoadedSource.next(company));
    }

}

子元件

import { Component, OnInit, OnDestroy } from '@angular/core';
import { SalesProcessService } from '../salesProcess.service';
import { Subscription } from 'rxjs/Rx';

@Component({
    selector: 'ex-company',
    template: require('./company.component.html'),
    styles: [require('./company.component.css')]
})
export class CompanyComponent implements OnInit, OnDestroy {
    company: any;
    private companySub: Subscription;
    constructor(
        private salesProcessService: SalesProcessService
        ) { }
    ngOnInit() {
        this.companySub = this.salesProcessService.companyLoaded$.subscribe(company => {
            this.company = company;
        });
    }
    ngOnDestroy() {
        this.companySub.unsubscribe();
    }
}

答案#2

考慮為 @Input() 或 @Output() 創建一個 Angular2 服務,該服務將傳遞超過一層或傳遞給不相關的組件。