如何在角度中的兄弟组件之间共享数据?

Mos*_*she 8 angular

我有一个带有3个兄弟组件的Angular应用程序,它们能够访问和更新变量"data".它们连接到路由器,但我想传递的数据是敏感的(api端点确定折扣)所以我不能使用cmp2 /:data

组件1有一个称为数据的对象,组件2和3需要接收这个数据对象.我认为这可以通过共享服务完成,但我不太确定如何让这个事件发射器工作..

我的index.html:

<router-outlet></router-outlet>
Run Code Online (Sandbox Code Playgroud)

第1部分:

<button [routerLink]=['cmp2/']>Go to Comp 2 </button>
<button [routerLink]=['cmp3/']>Go to Comp 3 </button>
Run Code Online (Sandbox Code Playgroud)

组件2和3:

{{ data }}
Run Code Online (Sandbox Code Playgroud)

Joo*_*eck 15

因为看起来你想要重定向到那些组件,你可以做的是在组件1上有一个事件发射器,点击它会将数据发送到父组件(全部3).然后在父级中捕获emit,并将其分配给传递给其他组件的数据.

COMPONENT1

import { Component, EventEmitter, Output } from '@angular/core';
import { Router }                          from '@angular/router';

@Component(...)
export class Component1 {
    @Output() redirect:EventEmitter<any> = new EventEmitter();

    data:any = {text: "example"};

    constructor(private router:Router){}

    changeComponent(url:string){
        this.redirect.emit(data);//emits the data to the parent
        this.router.navigate([url]);//redirects url to new component
    }
}
Run Code Online (Sandbox Code Playgroud)

Component2&Component3

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

@Component(...)
export class Component2 {
    @Input() data:any;
}
Run Code Online (Sandbox Code Playgroud)

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

@Component(...)
export class Parent {
    parentData:any;
}
Run Code Online (Sandbox Code Playgroud)

Parent.html

<component1 (redirect)="parentData=$event"></component1>
<component2 [data]="parentData"></component2>
<component3 [data]="parentData"></component3>
Run Code Online (Sandbox Code Playgroud)

如果你没有父服务器,另一个选择是有一个服务,你注入每个父服务器,然后接收器挂钩到OnInit生命周期钩子.这是有效的,因为如果在共享模块的提供者中,服务是单例.

服务

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

@Injectable()
export class SharingService{
    private data:any = undefined;

    setData(data:any){
        this.data = data;
    }

    getData():any{
        return this.data;
    }
}
Run Code Online (Sandbox Code Playgroud)

COMPONENT1

import { Component }      from '@angular/core';
import { Router }         from '@angular/router';
import { SharingService } form './sharing.service';

@Component(...)
export class Component1 {

    data:any = {text: "example"};

    constructor(private router:Router,
        private sharingService:SharingService){}

    changeComponent(url:string){
        this.sharingService.setData(this.data);
        this.router.navigate([url]);//redirects url to new component
    }
}
Run Code Online (Sandbox Code Playgroud)

Component2&Component3

import { Component, OnInit } from '@angular/core';
import { SharingService }    form './sharing.service';

@Component(...)
export class Component2 implements OnInit{
    data:any;

    constructor(private router:Router,
        private sharingService:SharingService){}

    ngOnInit(){
        this.data = this.sharingService.getData();
    }
}
Run Code Online (Sandbox Code Playgroud)

确保将其添加到模块的providers数组中.

import { SharingService } from './sharing.service';
...

@NgModule({
    ...
    providers: [ SharingService ]
})
Run Code Online (Sandbox Code Playgroud)

  • @Joo 当使用浏览器刷新按钮时,保存在共享服务中的数据将被删除,我们该如何处理? (3认同)

小智 5

由于您要求在兄弟组件之间共享数据,我们可以通过在服务中使用BehaviourSubject来实现。

BehaviorSubject 持有需要与其他组件共享的值。这些组件订阅数据,简单地返回 BehaviorSubject 值,而没有更改该值的功能。

服务.ts

import { Observable, BehaviorSubject } from 'rxjs';

export class Service {
       private data = new BehaviorSubject("")
       currentData = this.data.asObservable();

 constructor() { }

 setData(data) {
      this.data.next(data);
 }
Run Code Online (Sandbox Code Playgroud)

组件1.ts

import { Service } from '../service.service';

export class component1 implements OnInit {

data: any;

constructor (private service: Service) {}

sendDataToService() {
     this.service.setData(this.data);
}
Run Code Online (Sandbox Code Playgroud)

组件2.ts

import { Service } from '../../service.service';

export class component2 implements OnInit {

constructor ( private service: Service ) { }

ngOnInit() {
    this.service.currentData.subscribe(data => {
      console.log(data);
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 你忘记了“@Injectable”? (2认同)