【问题标题】: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 }}

【问题讨论】:

    标签: angular


    【解决方案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
    
    });
    

    另外,您可以关注thisthis

    【讨论】:

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

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

    如果你需要:

    OutputEventEmitter的简单解释

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

    【讨论】:

      猜你喜欢
      • 2021-01-04
      • 2018-02-17
      • 2018-12-19
      • 2017-10-01
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 2020-12-12
      • 2021-01-11
      相关资源
      最近更新 更多