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

Posted

技术标签:

【中文标题】如何以角度在兄弟组件之间共享数据?【英文标题】:How do I share data between sibling components in angular? 【发布时间】:2017-10-11 22:16:38 【问题描述】:

我有一个带有 3 个同级组件的 Angular 应用程序,它们能够访问和更新变量“数据”。它们已连接到路由器,但我要传递的数据是敏感数据(用于确定折扣的 api 端点),因此我无法使用 cmp2/:data

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

我的 index.html

<router-outlet></router-outlet>

组件 1:

<button [routerLink]=['cmp2/']>Go to Comp 2 </button>
<button [routerLink]=['cmp3/']>Go to Comp 3 </button>

组件 2 和 3:

 data 

【问题讨论】:

【参考方案1】:

由于您要求在同级组件之间共享数据,我们可以通过在服务中使用 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);
 

组件1.ts

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

export class component1 implements OnInit 

data: any;

constructor (private service: Service) 

sendDataToService() 
     this.service.setData(this.data);

组件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);
    );

【讨论】:

你忘了@Injectable【参考方案2】:

看起来您正在寻找重定向到这些组件,您可以做的是在组件 1 上设置一个事件发射器,单击时会将数据发送到父组件(所有 3 个组件)。然后在父级中捕获发射,并将其分配给传递给其他组件的数据。

组件1

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
    

组件2和组件3

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

@Component(...)
export class Component2 
    @Input() data:any;

父母

import  Component  from '@angular/core';

@Component(...)
export class Parent 
    parentData:any;

父.html

<component1 (redirect)="parentData=$event"></component1>
<component2 [data]="parentData"></component2>
<component3 [data]="parentData"></component3>

如果您没有父级,另一种选择是拥有一个服务,您将其注入每个父级,然后将接收器挂钩到 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;
    

组件1

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
    

组件2和组件3

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();
    

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

模块

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

@NgModule(
    ...
    providers: [ SharingService ]
)

【讨论】:

谢谢@Joo,我正在实施您的优雅解决方案,如果可行,会通知您。 @Joo 保存在共享服务中的数据会在使用点击浏览器刷新按钮时被删除,我们该如何处理??【参考方案3】:

Angular 可以在 Angular 的 $scope$rootScope 事件系统中通过 $emit, $broadcast and $on 在兄弟之间共享数据。

<div>
  <div ng-controller="SiblingOneCtrl1 as sib1" class="ng-scope">
    // SiblingOneCtrl
  </div>
  <div ng-controller="SiblingTwoCtrl2 as sib2" class="ng-scope">
    // SiblingTwoCtrl
  </div>
</div>

app.controller('SiblingOneCtrl1',
  function SiblingOneCtrl1 ($rootScope) 

  $rootScope.$on('rootScope:emit', function (event, data) 
    console.log(data); // 'Emit!'
  );

  $scope.$on('rootScope:broadcast', function (event, data) 
    console.log(data); // 'Broadcast!'
  );

  $rootScope.$on('rootScope:broadcast', function (event, data) 
    console.log(data); // 'Broadcast!'
  );

);

app.controller('SiblingOneCtrl2',
  function SiblingOneCtrl2($rootScope) 

  $rootScope.$emit('rootScope:emit', 'Emit!'); // $rootScope.$on
  $rootScope.$broadcast('rootScope:broadcast', 'Broadcast'); // $rootScope.$on && $scope.$on

);

另外,您可以关注this 和this

【讨论】:

对不起 eigenharsha,我很欣赏这个答案,但这是 Angular 而不是 AngularJS【参考方案4】:

由于您有多个接收者components,最好的方法是使用singleton 共享service。因为稍后如果您创建更多接收器components,则向每个人发送component 是不合适的。

如果你需要:

OutputEventEmitter的简单解释

https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

【讨论】:

以上是关于如何以角度在兄弟组件之间共享数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在彼此不直接链接的角度组件之间共享数据?

在兄弟组件之间共享数据(未按预期工作)

Angular 2 中兄弟组件之间的数据共享

Vue组件之间的数据共享

Vue组件之间的数据共享

Vue组件之间的数据共享