【问题标题】:How to share data between two different component in angular for different module如何在不同模块的角度中的两个不同组件之间共享数据
【发布时间】:2019-11-21 19:46:59
【问题描述】:

如何在 2 个不同模块的 2 个不同组件之间共享数据。

我有 2 个模块仪表板和偏好以及两个组件dashboard.component.ts 和preference.component.ts 分别

我创建了 bar.service.ts 服务来传递数据,我的服务包含以下代码

private messageSource = 'orderView';

  changeMessage(message: string) {
    this.messageSource = message;
  }

preference.component.ts 包含以下代码

this.bar.changeMessage('groupByView');

dashboard.component.ts 包含以下代码

console.log(this.bar.messageSource);

我正在使用路由和偏好显示偏好页面和仪表板显示仪表板页面。

当用户在偏好页面并将 messageSource 更改为 groupByView 时,它不会反映在仪表板页面上。

仪表板页面始终在 messageSource 中包含 orderView 值

【问题讨论】:

  • changeMessageconsole.log 是否在同步上下文中?
  • @BálintRéthy 的意思是?
  • 这意味着如果你先调用console.log然后再调用changeMes​​sage,即使在异步上下文中(例如随机点击事件),它也会在控制台上写入orderView

标签: angular typescript


【解决方案1】:

您可以使用 observables(它们高度集成到 Angular 中)。

服务(YourService):

@Injectable() // { providedIn: 'root' } ? read below
export class YourService {
  messageSourceSubject: BehaviorSubject<string> = new BehaviorSubject<string>('orderView');
  messageSource: Observable<string> = this.messageSourceSubject.asObservable();

    publishMessage(message: string): void {
      this.messageSourceSubject.next(message);
    }
}

您的服务必须在根服务中注册(providedIn Injectable 的属性,否则您必须将此服务放入某些提供程序(可能是您的根模块)中。

您的组件:

当你需要在 TypeScript 中(在组件 TS 代码中)获取数据时,你需要:

constructor(public yourService: YourService) {
  this.yourService
    .messageSource
    .subscribe(message => console.log(message));
  // don't forget to unsubscribe on destroy (`subscription.unsubscribe` - subscribe returns it) or `pipe(takeUntil(this.destroy))` - takeUntil is an RxJS operator from `rxjs/operators`.
}

如果您需要 HTML 格式:

<div>{{ yourService.messageSource | async }}</div>

async 关键字是一个 AsyncPipe(来自 @angular/common 的 CommonModule)。如果您使用 AsyncPipe,您无需在任何地方取消订阅,它会自行处理。

另外,如果你在组件中使用订阅,你一定不要忘记取消订阅(我在上面的代码中给出了一些 cmets)

不要忘记将所有内容导入到您的组件中。

另外,如果你在你的组件中使用ChangeDetectionStrategy.OnPush,你必须告诉 Angular 将来在这个组件上运行更改检测。可以使用ChangeDetectorRef依赖(可以通过DI获取)及其方法markForCheck来完成。

【讨论】:

  • 我之前尝试过同样的方法,但它也不起作用,所以只是删除了 observable 并使其变得简单
  • 然后,您必须提供更多上下文。可能是一些复制品。我还用有关更改检测策略的文本更新了答案。 Angular 的工作方式与您在问题中描述的方式不同。这有点复杂。
  • 好吧,我想我在这里犯了一些错误“您的服务必须在根服务中注册(providedIn 可注射的属性,否则您必须将此服务放入某些提供程序(可能是您的根模块)。”
  • 你能澄清一下我的cmets我到底需要做什么
  • 我已经在我的偏好模块提供者中传递了这个:[BarService]
【解决方案2】:

你可以使用主题

Working Demo

酒吧服务:

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

@Injectable()
export class BarService {

// Observable string sources
  private messageSource = new Subject<string>();
  messageSource$ = this.messageSource.asObservable();


  constructor() { }


  changeMessage(message: string) {
     this.messageSource.next(message);
  }

}

偏好组件:

import { Component, OnInit } from '@angular/core';
import { BarService } from '../bar.service';
@Component({
  selector: 'app-preference',
  templateUrl: './preference.component.html',
  styleUrls: ['./preference.component.css']
})
export class PreferenceComponent implements OnInit {

  constructor(private barService: BarService) { }

  ngOnInit() {

  }
  onChange() {
    this.barService.changeMessage(`Update dashboard at ${ new Date()}`)
  }

}

偏好模板:

<p>
preference works! 
<button (click)="onChange()">Update Dashboard</button>
</p>

仪表板组件:

import { Component, OnInit } from '@angular/core';
import { BarService } from '../bar.service';
@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

  changeMessage: any;
 constructor(private barService: BarService) { }

  ngOnInit() {
    this.barService.messageSource$.subscribe((res)=>{
      this.changeMessage = res;
    });
  }

}

仪表板模板:

<p>
dashboard works! {{changeMessage}}
</p>

【讨论】:

  • 我尝试了您的代码,但不幸的是,当我转到首选项页面和仪表板页面时,这并没有触发。 barService.messageSource$.subscribe((res)=>{ console.log(res); });
  • 它至少在 BehaviorSubject 的情况下触发
  • 当我们有 2 个不同的模块在组件之间传递数据时有什么区别
  • 在 root 上注入服务意味着什么?
  • ‘root’表示我们要在根级别提供服务
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 2019-02-13
相关资源
最近更新 更多