【问题标题】:Angular - How to subscribe data one time, in one request, and use it in child components?Angular - 如何在一个请求中一次性订阅数据,并在子组件中使用它?
【发布时间】:2020-12-04 16:21:56
【问题描述】:

我正在开发的网站有一个主要组件,我正试图使其可重用。是这样的:

-> parent
    parent.component.html
    parent.component.scss
    parent.component.ts
   -> child_1
       child_1.component.html
       child_1.component.scss
       child_1.component.ts
   -> child_2
       child_2.component.html
       child_2.component.scss
       child_2.component.ts
(...)
-> services
  -> parent-services
      parent.service.ts

parent.service.ts 有 http 方法,但我需要在 child_1.component.ts 和 child_2.component.ts 中返回一个 http 请求,以便将来自该请求的数据订阅到可重用变量。

如何在一个服务请求中获取数据,然后订阅一次来填充我的 html 页面,该页面将用于 child_1.component.ts 和 child_2.component.ts以不同的方式?

*Obs.:在订阅期间我做了一些数据操作,比如验证它是否为 null 然后添加一些默认值,然后复制粘贴这个块代码似乎不是一个好的解决方案。

【问题讨论】:

  • 这个解决方案对我没有帮助:stackoverflow.com/questions/45201555/…
  • 当它准备好时,您可以订阅并从父组件向 child_1 和 child_2 发送 http 响应。
  • 不错!一段时间后,我了解了如何处理相关和不相关组件之间的数据(并非总是适用 EventEmitter)。很棒的教程可以在这里找到:fireship.io/lessons/…

标签: angular typescript service observable


【解决方案1】:

您可以在服务中使用 BehaviorSubject 作为可观察对象。此 BehaviorSubject 将包含您要在两个组件中使用的公共变量的值。

您的 api 调用将在您的服务的构造函数中,并且每当此 api 调用得到响应时,此 BehaviorSubject 将在您的服务中分配一个值。

在您的组件中保持订阅此 Subject 的 observable,因为它会在某个时间点具有价值,您可以轻松地在您的组件中获得该价值。

请考虑以下代码以供参考:-

parent.service.ts :-

import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';

export class ParentService {
children = new BehaviorSubject([]);
sharedChildren = this.children.asObservable();
apiUrl = 'https://jsonplaceholder.typicode.com';

constructor(private http:HttpClient) {
    this.http.get(`${this.apiUrl}/users`).subscribe((users: any) => {
          console.log('Children fetched on application boot up :-\n', users);
          this.children.next(users);
        })
    }
}

child_1.component.ts :-

import { ParentService } from 'yourParentServiceClassPath';
import { Component, OnInit } from '@angular/core';

export class Child_1Component implements OnInit{
    we_siblings;
    constructor(private parentService: ParentService) {}
    ngOnInit() {
        this.parentService.sharedChildren.subscribe((children: any) => {
            this.we_siblings = children;
            console.log('We siblings are', this.we_siblings);
        })
    }
}

同样,您可以在 child2_component.ts 或任何其他组件中创建一个 we_siblings 变量,并遵循我们在 child1_component.ts 中遵循的相同内容

由于您在 Child_1Component 的构造函数中实例化了 ParentService,所以它的构造函数将在应用程序第一次加载时被调用。因此,调用 api,从 api 获取数据并将其传递给组件中订阅的 sharedChildren observable。

【讨论】:

  • 谢谢!帮了我很多:D
  • 乐于助人! @戴维森利马
【解决方案2】:

您可以创建一个服务并使用 BehaviorSubject 如下所示,在 child 中您可以通过 asObservable() 获取数据:

服务:

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

@Injectable({
  providedIn: 'root'
})
export class UserService {
    private userDataSource: BehaviorSubject<Array<any>> = new BehaviorSubject([]);
    userData = this.userDataSource.asObservable();

    updateUserData(data) {
      this.userDataSource.next(data);
    }
}

在父组件中:

constructor(
    private myHttpService: MyService,
    private userService: UserService,
  ) { }

arrayData: any[] = [];
flag = false;

fetchData() {
 this.myHttpService.fetchApiData().subscribe(
      data => {
        this.arrayData = data;
        flag = true;
      },
      error => {
        console.log("Error");
      }
    )
  if (flag){
    this.userService.updateUserData(this.arrayData);
  }
}

在子组件中:

dataArray: any[] = [];

ngOnInit(): void {
    this.userService.userData.subscribe(data => this.dataArray = data);
  }

现在您可以在子组件的 ts 和 html 中使用 dataArray 的值了。

【讨论】:

    猜你喜欢
    • 2019-11-14
    • 2019-07-22
    • 2018-10-28
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多