如何为非父子Angular 2组件创建服务

时间:2017-06-29 12:45:06

标签: angular service

我真的很难为“无关的”Angular 2组件创建服务。但是,父子关系没有问题(我使用绑定或事件发射器)。

我有3个文件:

  1. 应携带数据的StatsService。
  2. 生成足球镜头的MatchBoard组件
  3. StatsComponent,用于在屏幕上显示拍摄张数。
  4. 但是我已经阅读了官方的A2文档并且仍然无法找到解决方案,因此我已经处理了几个小时了。

    我想要的是:我只想生成镜头(每2秒),用服务抓住它们并发送到StatsComponent,以便它显示屏幕上的镜头数量。那很简单。

    StatsService组件

    import { Injectable } from '@angular/core';
    import { Subject }    from 'rxjs/Subject';
    
    @Injectable()
    export class StatsService {
      private homeTeamShots = new Subject<any>();
      homeTeamShots$ = this.homeTeamShots.asObservable();
      publishData(data:any){
        this.homeTeamShots.next(data);
      }
    
    }
    

    MatchBoard组件

    import { Component, Input, OnInit, OnChanges } from '@angular/core';
    import {StatsService} from '../stats.component/stats.service';
    
    @Component({
      selector: 'match-board',
      templateUrl: './matchboard.component.html',
      styleUrls: ['./matchboard.component.css']
    })
    
    export class MatchBoard implements OnChanges {
      homeTeamShots:number = 0;
      constructor(private _statsService:StatsService) {
        this._statsService.homeTeamShots$.subscribe(
          data => {
            console.log('matchboard received this: ' + data);
          }
        )
      }
      ngOnChanges(){
    
      }
    
      onHomeTeamShot(){
        this.homeTeamShots += 1;
        this._statsService.publishData(this.homeTeamShots);
      }
    
      ngOnInit(){
        // shots are taken every 2 seconds as a example
        setInterval(()=> this.onHomeTeamShot(), 2000);
      }
    
    }
    

    和StatsComponent

    import { Component, Input, OnInit, OnChanges } from '@angular/core';
    import {StatsService} from '../stats.component/stats.service';
    
    @Component({
      selector: 'stats',
      templateUrl: './stats.component.html',
      styleUrls: ['./stats.component.css'],
      providers: [StatsService]
    })
    export class StatsComponent implements OnChanges {
      homeTeamShots:number;
      constructor(private _statsService:StatsService) {
        this.homeTeamShots = 0;
        this._statsService.homeTeamShots$.subscribe(
          data => {
            this.homeTeamShots = data;
            console.log('Sibling2Component-received from sibling1: ' + data);
          }
        );
      }
    
      ngOnChanges(){
    
      }
    
      onHomeTeamShot() {
        this.homeTeamShots += 1;
        console.log('number of shots in stats now ' + this.homeTeamShots);
        this._statsService.publishData(this.homeTeamShots);
      }
    
      ngOnInit(){
        setInterval(()=> console.log(this.homeTeamShots), 2050);
      }
    }
    

    在控制台中,我得到'matchboard收到了这个:来自MatchBoard组件的2(然后是3,然后是4正常)'。 但问题始于StatsComponent - 它在'subscribe'之后被卡住并且一直只记录'0'。

    我尝试在statsComponent中调用onHomeTeamShot(),但它从头开始一直显示“1”,也不会改变。

2 个答案:

答案 0 :(得分:1)

原因是行

providers: [StatsService]
StatsComponent中的

。这意味着StatsComponent拥有自己的服务实例。 解决方案是让组件中的提供程序仅在三个组件之上,并从StatsComponent中删除该行。

您可以在此处找到有关此内容的更多信息:https://angular.io/guide/hierarchical-dependency-injection

答案 1 :(得分:1)

将所有逻辑转移到服务上,并利用Observables的力量来完成繁重的工作。

在您的服务中,使用.interval()创建一个Observable。这将照顾您的投票。您甚至不需要publishData(),因为您已经在使用Subject。我创建了一个名为generateShots()

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

@Injectable()
export class StatsService {
    private homeTeamShots = new Subject<any>();
    homeTeamShots$ = this.homeTeamShots.asObservable();

    generateShots() {
        return Observable.interval(2000)
            .map(ticks => this.homeTeamShots$.next(ticks));
             //.interval() returns a single integer, starting from 0,1,2....
             //just simply update your subject with that value.
    }

}

现在,要在MatchBoard组件中“开始”倒计时,只需订阅generateShots()

ngOnInit() {
    this._statsService.generateShots()
        .subscribe(shots => this.homeTeamShots = shots);
    //this.homeTeamShots will increment from 0 to 1,2,3.... every 2000ms
}

要在StatsComponent中显示您的镜头,请订阅homeTeamShots$ Subject

ngOnInit() {
    this._statsService.homeTeamShots$.subscribe(
        data => {
            this.homeTeamShots = data;
            console.log('Sibling2Component-received from sibling1: ' + data);
        }
    );
}

瞧,您有两个组件通过单个共享服务(单例)同步数据。干净。