Angular2 - 使用服务在组件之间共享数据

Angular2 - Sharing Data Between Components Using Service

我正在尝试使用公共共享服务在组件之间共享数据。这就是服务。

@Injectable()
export class JobService {
    public jobType=null;
    public examples=[];
}

这是我的第一个组件。组件内的完整代码太长,所以我刚刚添加了一个 ... 来表示其余代码,但在该组件内,服务的 jobTypeexamples 变量是设置。

@Component({
            selector: 'app-job',
            templateUrl: './job.component.html'
})
export class JobComponent implements OnInit {

          constructor(private jobService: JobService, private authService: AuthService, private router: Router) {
            }
    ...

}

第二个分量是

@Component({
    selector: 'app-preview',
    template:'./preview.component.html'
})
export class PreviewComponent implements OnInit {

    jobType;
    examples;

    constructor(private jobService: JobService) {
    }  
    ngOnInit() {

        this.jobType=this.jobService.jobType;
        this.examples=this.jobService.examples;
    }

}

所以我们的想法是它应该能够获取 JobComponent.

内服务中设置的 jobTypeexamples 变量

服务本身在模块文件中提供

@NgModule({
    declarations: [
        JobComponent,
        JobListComponent,
        JobDetailsComponent,
        PreviewComponent
    ],
    imports: [
        CommonModule,
        FormsModule,
        RouterModule,
        TabsModule
    ],
    providers: [JobService]
})
export class JobModule {

}

据我了解,这意味着 JobService 仅实例化一次并在组件之间共享。

问题出现在 JobComponent 的 html 模板中。它包含一个路由器 link 以在新选项卡中打开 PreviewComponent

<a target="_blank" routerLink="/preview">Preview</a>

打开这个link的时候,JobService里面的变量已经在JobComponent里面设置好了(我查了一下是真的)。 /preview 路由与 PreviewComponent 关联。当新 window 打开时 和 PreviewComponents 读取 JobService 变量,它们尚未设置,这让我相信 PreviewComponent 已经创建了一个全新的 JobService 实例。然而,根据 如果 JobService 在模块文件中仅提供一次,则不应发生这种情况。谁能告诉我为什么 JobService 似乎没有在这两个组件之间共享?

这是因为您在新 window 中打开页面。 JobService 的状态未被保留。一种可能的解决方案是使用 url 查询参数将 JobService 的状态传递给预览组件并在新页面中重建服务,例如,导航到 /preview?jobType=something&examples=are,comma,separated,list 或将状态保存在浏览器(本地存储、cookie 等)并在页面初始化时读取它

要保存共享资源的状态,您应该使用 BehaviorSubjects。

@Injectable()
export class JobService {
    public jobType$: BehaviorSubject<any> = new BehaviorSubject('');
    public examples$: Behavior Subject<any[]> = new BehaviorSubject([]);
    public jobTypes = null;
    public examples = [];

    setJobType(jobType) {
        this.jobTypes = jobType;
        this.jobType$.next(this.jobTypes);
    }
    //set the same way for examples
}

然后在你的每个组件中。

@Component({
            selector: 'app-job',
            templateUrl: './job.component.html'
})
export class JobComponent implements OnInit {

  constructor(private jobService: JobService, private authService: AuthService, private router: Router) {}

  //somewhere like ngOnInit subscribe to jobType$ and or examples$

  //on some event or trigger of the ui call the setJobType method with changes.
}


@Component({
    selector: 'app-preview',
    template:'./preview.component.html'
})
export class PreviewComponent implements OnInit {

    jobType;
    examples;

    constructor(private jobService: JobService) {
    }  
    ngOnInit() {
        this.jobService.jobType$.subscribe(result => this.jobType = result);
        this.jobService.examples$.subscribe(result => this.examples = result);
    }
}