简体   繁体   English

如何在 angular 的兄弟组件之间共享数据?

[英]How do I share data between sibling components in angular?

I have an Angular application with 3 sibling components, they are able to access and update the variable "data".我有一个带有 3 个兄弟组件的 Angular 应用程序,它们能够访问和更新变量“数据”。 They are connected to the router, but the data I want to pass is sensitive (api endpoints to determine discounts) so I cannot use cmp2/:data它们连接到路由器,但我想传递的数据是敏感的(api 端点来确定折扣)所以我不能使用 cmp2/:data

Component 1 has an object called data and Components 2 and 3 need to receive this data object.组件 1 有一个名为 data 的对象,组件 2 和 3 需要接收这个数据对象。 I think this can be done with a shared service, but I'm not quite sure how to get this event emitter to work..我认为这可以通过共享服务来完成,但我不太确定如何让这个事件发射器工作..

My index.html:我的 index.html:

<router-outlet></router-outlet>

Component 1:组件 1:

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

Components 2 and 3:组件 2 和 3:

{{ data }}

As it looks like you are looking to redirect to those components, what you can do is have an event emitter on component one, that on click will emit the data to the parent(of all 3).看起来您希望重定向到这些组件,您可以做的是在组件一上有一个事件发射器,单击时会将数据发送到父级(所有 3 个)。 Then in the parent you would catch the emit, and assign that to data that you pass into the other components.然后在父级中,您将捕获发射,并将其分配给您传递给其他组件的数据。

Component1组件 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
    }
}

Component2 & Component3组件 2 和组件 3

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

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

Parent家长

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

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

Parent.html父.html

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

Another option, if you don't have a parent, is to have a service, that you inject into each parent, and then for the receivers hook into the OnInit lifecycle hook.如果您没有父级,另一种选择是拥有一个服务,将其注入到每个父级中,然后让接收者挂钩到 OnInit 生命周期挂钩中。 This works because services are a singleton if in a provider of a shared module.这是有效的,因为如果在共享模块的提供者中,服务是单例的。

Service服务

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

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

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

    getData():any{
        return this.data;
    }
}

Component1组件 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
    }
}

Component2 & Component3组件 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();
    }
}

Make sure you add it to providers array of the module.确保将其添加到模块的 providers 数组中。

Module模块

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

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

Since you have asked to share the data between sibling components we can achieve it by using BehaviourSubject in service.由于您要求在兄弟组件之间共享数据,我们可以通过在服务中使用BehaviourSubject来实现。

The BehaviorSubject holds the value that needs to be shared with other components. BehaviorSubject 持有需要与其他组件共享的值。 These components subscribe to data which is simple returning the BehaviorSubject value without the functionality to change the value.这些组件订阅数据,简单地返回 BehaviorSubject 值,而没有更改该值的功能。

Service.ts服务.ts

import { Observable, BehaviorSubject } from 'rxjs';

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

 constructor() { }

 setData(data) {
      this.data.next(data);
 }

Component1.ts组件1.ts

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

export class component1 implements OnInit {

data: any;

constructor (private service: Service) {}

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

Component2.ts组件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);
    });
}

Since you have multiple receiver components , Best way is to use a singleton shared service .由于您有多个接收器components ,最好的方法是使用单例共享service Because later if you create more receiver components , emitting to each and every individual component would not be appropriate.因为以后如果你创建更多的接收器components ,发射到每个单独的component是不合适的。

Incase you need :如果您需要:

Simple explanation for Output and EventEmitter OutputEventEmitter简单解释

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

Angular has the facility to share data between siblings through $emit, $broadcast and $on in angular's $scope and $rootScope event system. Angular 可以通过$emit, $broadcast and $on在 angular 的$scope$rootScope事件系统中在兄弟姐妹之间共享数据。

<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

});

also, you can follow this and this另外,你可以按照这个这个

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM