【问题标题】:Angular transfer data between two unrelated components两个不相关组件之间的角度传输数据
【发布时间】:2021-12-29 07:14:38
【问题描述】:

我的 Angular 项目中有两个完全独立的元素。第一个显示车牌列表和每个车牌的两个按钮:“查看当前位置”和“查看过去 24 小时的位置”。这两个按钮重定向到同一个组件,该组件根据变量“方法”在地图中显示一些点。单击按钮时,我想将“方法”设置为某个值,但我不知道该怎么做。

我尝试过关于主题/订阅的事情,但对我不起作用。我可能没有正确应用它,因为我对它的工作原理不是很有信心。在我找到的示例中,主题是由一些 @Injectable 提出的,但我正在使用两个 @Component。

谢谢大家。

编辑:我将尝试解释我的尝试。

我有服务

import { Inject, Injectable } from "@angular/core";
import { MatriculasListadoComponent } from "../components/matriculas-listado/matriculas-listado.component";
import { Metodos } from "../models/metodos";

@Injectable({
  providedIn: 'root'
})
export class ConexionDataService {
    metodoBoton: Subject<Metodos>
  
    constructor() {
      this.metodoBoton = new Subject<Metodos>();
    }
    
    } 

然后我的组件中有一个方法,我想从该方法发送数据,称为单击按钮:

constructor(private matriculaService: MatriculaService, private conexionDataService: ConexionDataService) {
    this.dataSource = new MatTableDataSource<Matricula>([]);
  }

...

enviarMetodo(metodo:Metodos) {
    this.conexionDataService.metodoBoton.next(metodo);
  }

我在要接收数据的组件中有这个 NgOnInit

providers: [ListaPosicionesService, DatePipe, ConexionDataService]

...

ngOnInit(): void {
    this.conexionDataService.metodoBoton.subscribe(log=> {
      this.metodo=log
      console.log(log)
    })

我将日志显示为“未定义”。可能我做得不好,因为我根本不明白这些服务是如何工作的......

【问题讨论】:

  • 请添加更多细节,提供代码 sn-p 这将有助于理解为什么它不起作用。
  • 您需要提供您的代码。这是否回答了您的问题:stackoverflow.com/questions/51660156/…
  • @DevangPatel 我已经添加了代码,希望你能帮助我
  • @Anuj.T 代码添加
  • @Videgain 只需将服务中的主题更改为 behaviorSubject。在我的回答中,我分享了如何使用行为主题的演示。

标签: angular angular-components subscribe


【解决方案1】:

在缺少直接连接的组件之间传递数据时,例如兄弟姐妹、孙辈等,您应该使用共享服务。当您有应该同步的数据时,我发现 RxJS BehaviorSubject 在这种情况下非常有用。

您也可以使用常规 RxJS 主题通过服务共享数据,但这就是我更喜欢 BehaviorSubject 的原因。

  1. 它总是会在订阅时返回当前值 - 无需调用 onnext
  2. 它有一个 getValue() 函数来提取最后一个值作为原始数据。
  3. 它确保组件始终接收最新数据。

这是工作演示 --> BehaviorSubject | Stackblitz

共享服务

private metodoSource = new BehaviorSubject({ id: '1', name: 'default' });
metodoCurrent = this.metodoSource.asObservable();

父组件

constructor(private data: DataService)

changeMetodo() {
//this is sample data you can use your metodo model
 let data = {
   id: '2',
   name: 'xyz',
   changeFrom: 'homeComponent',
 };
 this.data.changeMetodo(data);
}

兄弟组件

constructor(private data: DataService)
ngOnInit() {
this.metodoSubscription = this.data.metodoCurrent.subscribe((metodo) => {
  this.metodo = metodo;
});

}

每当父级使用 next 方法发出时,您都可以接收数据 在其他组件中并对其采取行动。

在我创建的演示中,它也会重定向,并且更新的数据将在我们重定向到的其他组件中可用。

【讨论】:

    【解决方案2】:

    您可以使用NgRx 之类的库。这将使您可以轻松地在组件之间进行通信,而无需在它们之间创建“父子”关系。

    只需从当前组件调度一个动作并创建一个效果来捕获并触发另一个组件

    【讨论】:

      【解决方案3】:

      如果它是一个复杂的应用程序,那么保持状态的 NGRX 是一个好主意。但是,对于一个简单的应用程序来说,它有很多样板代码,其中 BehaviourSubjects 可能是您所追求的。

      BehaviourSubjects 是需要初始化的可观察对象。它们往往位于您可能已定义的现有服务上(通过您的组件构造函数注入的 DI)。

      BehaviorSubject vs Observable?

      流程是这样的……

      在服务上定义您的 BehaviourSubject。我的是一个名为 CommonSvc 的服务。这是一篇关于服务的好文章。 https://angular.io/tutorial/toh-pt4

      public loadingSub: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
      

      创建一个公共方法来暴露主题并设置下一个值

        public setLoading(loading: boolean,): void {
            this.loadingSub.next(loading);
        }
      

      在您的组件上,将您的服务注入到构造函数中。

      private commonSvc: CommonService
      

      您现在可以直接访问 BehaviourSubject。像这样。

        this.commonSvc.loadingSub
        .subscribe((loading) => {
          this.loading = loading;
        });
      

      ...如果您需要更新 BehaviourSubject,请调用公共方法。

      this.commonSvc.setLoading(true);
      

      现在,这种方法的美妙之处在于,在您订阅 BehaviourSubject 的任何地方,都会显示相同的值。您可以在组件中的任何位置注入服务,因此它也非常灵活。

      缺点是当你有很多它们(主题和行为主题)时,它们可能会变得难以管理。这就是 NGRX 的用武之地。

      PS。如果您正在订阅订阅,请不要忘记在完成后取消订阅。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-12
        • 2018-12-27
        • 2017-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        相关资源
        最近更新 更多