使用Angular 2中的服务在组件之间发送数据

使用Angular 2中的服务在组件之间发送数据,angular,angular2-services,Angular,Angular2 Services,我正在尝试使用服务在两个组件之间发送数据。但是,当“子”组件首次加载时,我在填充数据方面遇到了问题 当您从release-list.component上的无序列表中选择“release”时,它将通过路由器出口加载release-detail.component。release-detail.component应该显示发布艺术家 如果您选择了一个版本,然后再次选择一个版本,则该功能将起作用。但在填充数据之前,我必须“加载”release-detail.component两次。我觉得我很接近,但我肯

我正在尝试使用服务在两个组件之间发送数据。但是,当“子”组件首次加载时,我在填充数据方面遇到了问题

当您从release-list.component上的无序列表中选择“release”时,它将通过路由器出口加载release-detail.component。release-detail.component应该显示发布艺术家

如果您选择了一个版本,然后再次选择一个版本,则该功能将起作用。但在填充数据之前,我必须“加载”release-detail.component两次。我觉得我很接近,但我肯定错过了什么。任何帮助都将不胜感激

谢谢

我提到了a和

release.service.ts

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

import { MockReleaseList, ReleaseInterface } from './mock-releases';

@Injectable()

export class ReleaseService {
    private releaseSubject$ = new Subject();

    getReleases(): ReleaseInterface[] {
        return MockReleaseList;
    }

    getRelease() {
        return this.releaseSubject$;
    }

    updateRelease(release: {artist: string, title: string, category: string}[]) {
        // console.log(release);
        this.releaseSubject$.next(release);
    }

}
release-list.component.ts

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

import { Router } from '@angular/router';
import { Location } from '@angular/common';

import { ReleaseService } from '../../../shared/services/release.service';
import { MockReleaseList, ReleaseInterface } from '../../../shared/services/mock-releases';

@Component({
  selector: 'ostgut-releases',
  template: `
    <h3>Label List</h3>
    <ul>
        <li *ngFor="let release of releases" (click)="onSelect(release)">{{ release.artist }}</li>
    </ul>
    <router-outlet></router-outlet>
  `,
})
export class ReleaseListComponent implements OnInit { 
    private releases: ReleaseInterface[];

    constructor (
        private _router: Router,
        private _releaseService: ReleaseService
    ) {}

    ngOnInit(): ReleaseInterface[] {
        return this.releases = this._releaseService.getReleases();
    }

    onSelect(release: any): void {
        this._releaseService.updateRelease(release);
        this._router.navigate(['/release-list/release-detail', release.category]);
    }

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

import { Router, ActivatedRoute, Params } from '@angular/router';

import { ReleaseService } from '../../../../shared/services/release.service';
import { ReleaseInterface } from '../../../../shared/services/mock-releases';

@Component({
  selector: 'ostgut-release-detail',
  template: `
    <h3>Release Detail</h3>
    <p>{{ release.artist }}</p>
  `,
})
export class ReleaseDetailComponent implements OnInit { 
    private routeParam: string;
    private routeParamSub: any;
    private release: any;

    constructor(
        private _activatedRoute: ActivatedRoute,
        private _router: Router,
        private _releaseService: ReleaseService
    ) {}

    ngOnInit(): void {
        this.release = this._releaseService.getRelease().subscribe(release=>{
            return this.release = release;
        });
    }

}
从'@angular/core'导入{Component,OnInit};
从'@angular/Router'导入{Router};
从“@angular/common”导入{Location};
从“../../../shared/services/release.service”导入{ReleaseService};
从“../../../shared/services/mock Release”导入{MockReleaseList,ReleaseInterface};
@组成部分({
选择器:'ostgut releases',
模板:`
标签清单
    {{release.artist}
`, }) 导出类ReleaseListComponent实现OnInit{ 私有发布:ReleaseInterface[]; 建造师( 专用路由器:路由器, 私有发布服务:发布服务 ) {} ngOnInit():ReleaseInterface[]{ 返回this.releases=this.\u releaseService.getReleases(); } onSelect(释放:任意):无效{ 此.u releaseService.updateRelease(发布); 此.u router.navigate(['/release list/release detail',release.category]); } }
release-detail.component.ts

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

import { Router } from '@angular/router';
import { Location } from '@angular/common';

import { ReleaseService } from '../../../shared/services/release.service';
import { MockReleaseList, ReleaseInterface } from '../../../shared/services/mock-releases';

@Component({
  selector: 'ostgut-releases',
  template: `
    <h3>Label List</h3>
    <ul>
        <li *ngFor="let release of releases" (click)="onSelect(release)">{{ release.artist }}</li>
    </ul>
    <router-outlet></router-outlet>
  `,
})
export class ReleaseListComponent implements OnInit { 
    private releases: ReleaseInterface[];

    constructor (
        private _router: Router,
        private _releaseService: ReleaseService
    ) {}

    ngOnInit(): ReleaseInterface[] {
        return this.releases = this._releaseService.getReleases();
    }

    onSelect(release: any): void {
        this._releaseService.updateRelease(release);
        this._router.navigate(['/release-list/release-detail', release.category]);
    }

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

import { Router, ActivatedRoute, Params } from '@angular/router';

import { ReleaseService } from '../../../../shared/services/release.service';
import { ReleaseInterface } from '../../../../shared/services/mock-releases';

@Component({
  selector: 'ostgut-release-detail',
  template: `
    <h3>Release Detail</h3>
    <p>{{ release.artist }}</p>
  `,
})
export class ReleaseDetailComponent implements OnInit { 
    private routeParam: string;
    private routeParamSub: any;
    private release: any;

    constructor(
        private _activatedRoute: ActivatedRoute,
        private _router: Router,
        private _releaseService: ReleaseService
    ) {}

    ngOnInit(): void {
        this.release = this._releaseService.getRelease().subscribe(release=>{
            return this.release = release;
        });
    }

}
从'@angular/core'导入{Component,OnInit,Input};
从'@angular/Router'导入{Router,ActivatedRoute,Params};
从“../../../../shared/services/release.service”导入{ReleaseService};
从“../../../../shared/services/mock Release”导入{ReleaseInterface};
@组成部分({
选择器:“ostgut发布详细信息”,
模板:`
发布细节
{{release.artist}

`, }) 导出类ReleaseDetailComponent实现OnInit{ 私有路由图:字符串; 私家路:任何; 私人释放:任何; 建造师( 专用_activatedRoute:activatedRoute, 专用路由器:路由器, 私有发布服务:发布服务 ) {} ngOnInit():void{ this.release=this.\u releaseService.getRelease().subscribe(release=>{ 返回此项。释放=释放; }); } }
我认为问题可能是您的
主题
在您的
发布详情组件
中订阅它之前发布了它的值。当您第二次执行此操作时,将发布一个新的
Release
,并且已经创建了
ReleaseDetailComponent
,这意味着它将正常工作

要解决此问题,您可以尝试在服务中使用
行为主题
而不是常规的
主题
BehaviorSubject
将为您提供最新发布的值,即使您在上一个值发布后订阅了该值。不过,它也需要一个默认值,因此您可能希望在
ReleaseDetailComponent
模板中添加一些空检查

实现可以如下所示:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; // <-- note the import!

import { MockReleaseList, ReleaseInterface } from './mock-releases';

@Injectable()

export class ReleaseService {
    private releaseSubject$ = new BehaviorSubject(undefined);

   // The rest is the same

}
如果您想进一步了解不同类型的
主题
,请参阅以下文档:


我希望这有帮助

考虑使用
BehaviorSubject
作为代理。订阅返回主题的最后一个值后,延迟加载的组件将始终使用最近的值进行更新:

@Injectable
export class ReleaseService {
    releaseSource: BehaviorSubject = new BehaviorSubject(null);

   // No difference when it comes to subscribing to the BehaviorSubject
}

BehaviorSubject
在操作中的基本示例:

我认为您在这里混合了两个概念。有两种方法可以做到这一点:

  • 在发布详细信息组件中,使用
    @Input
    声明
    发布
    ,并从发布列表中传递它。您可以将其作为组件中的变量使用。没有主题,就没有订阅
  • 您使用了如上所述的服务,但已经加载了详细信息。类似于将其嵌入发布列表html,但将
    *ngIf
    设置为false,不显示它。当您将所选版本放入主题并启动时,您可以将
    *ngIf
    设置为true,显示版本详细信息部分

  • 明亮的谢谢你,弗雷德里克!RxJS的概念对我来说仍然是新的,所以我有一种感觉,那就是我会有点偏离正轨。我需要更改的另一件事是ReleaseDetailComponent和ngonit钩子-->this.release=this.\u releaseService.getRelease().subscribe(release=>{return this.release=release;});很乐意帮忙!:)谢谢你,先生。你和弗雷德里克都说对了。非常感谢!完成。谢谢你,赛姆