【问题标题】:Share service API data between initial components in Angular 6在 Angular 6 中的初始组件之间共享服务 API 数据
【发布时间】:2018-10-19 22:37:44
【问题描述】:

我正在尝试创建一个带有类别的导航栏和一个也使用这些类别的主页组件。我不想调用我的 API 两次,我将在其他地方使用相同的类别变量。我尝试执行以下操作:

数据服务

该服务从api url获取数据并返回可订阅对象。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  api_url: string = "https://apiurlhere";
  categories: Object;

  constructor(private http: HttpClient) { }

  getCategories(){
    return this.http.get(this.api_url+'/categorylisting/?z=1');
  }

  getZones(){
    return this.http.get(this.api_url+'/zones/');
  }

}

导航栏组件

导航栏组件利用类别变量来显示不同的选项,这很好用,因为订阅在这个组件中。

import { Component, OnInit } from '@angular/core';
import { trigger, state, transition, animate, style } from '@angular/animations';
import { DataService } from '../data.service';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.scss'],
  animations: [
    trigger('slideInOut', [
      state('in', style({
        overflow: 'hidden',
        height: '*'
      })),
      state('out', style({
        overflow: 'hidden',
        height: '0px'
      })),
      transition('in => out', animate('400ms ease-in-out')),
      transition('out => in', animate('400ms ease-in-out'))
    ])
  ]
})
export class NavbarComponent implements OnInit {

  categories: Object;

  constructor(private data:DataService) { }

  ngOnInit() {
    this.data.getCategories().subscribe( data => {
      this.categories = data
      for(let category in this.categories){
        this.categories[category].productsOpen='out';
        for(let product in this.categories[category].product){
          this.categories[category].products[product].active = false;
        }
      }
      this.data.categories = this.categories;
    });
  }

  openProducts(index){
    this.categories[index].productsOpen = this.categories[index].productsOpen === 'out' ? 'in' : 'out';
  }

  setActiveProduct(index, productIndex){
    for(let category in this.categories){
      for(let product in this.categories[category].products){
        this.categories[category].products[product].active = false;
      }
    }
    this.categories[index].products[productIndex].active = true;
  }

}

主页组件

我的 Home 组件也使用了 categories 变量,所以我想知道如何在此处获取它,因为即使它在服务中发生更改,它也始终未定义。

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  categories: Object;

  constructor(private data:DataService) { }

  ngOnInit() {
    this.categories = this.data.categories;
  }

}

我这样做对吗?我习惯于 react 和 redux,并且每次调用 setState 来更改状态时,render 方法都会运行,angular 何时知道组件的变量何时更改?我只想用我的数据保存一个全局变量,这样我就可以重用它而无需每次都调用 API。谢谢。

【问题讨论】:

  • 如何填充导航栏和主页组件?它们是在模板中静态启动的吗?如果是这样,您可以在代码块示例中将其添加到您的问题中
  • 您可以使用简单的缓存服务将数据实例存储在变量中,并且您的 api 调用能够强制更新数据(这意味着从服务器发出新请求)否则返回缓存的数据。

标签: javascript angular typescript


【解决方案1】:

您可以在服务中缓存 observable,例如:

export class DataService {

someProperty;

  api_url: string = "https://apiurlhere";
  categories: Object;

  constructor(private http: HttpClient) { }

  getCategories(){
   if(!this.someProperty) {
     this.someProperty = this.http.get(this.api_url+'/categorylisting/?z=1');
   }
     return this.someProperty;
  }
}

您也可以选择 angular Http interceptors 或者您也可以选择 rxjs 运算符 shareReplay

【讨论】:

  • 这就是我要找的东西,唯一的问题是,由于它没有在检查时被初始化,它确实运行了两次调用,我的两个组件同时加载,有没有在加载同级组件之前“等待”直到完成的方法?
  • 这是工作演示 stackblitz.com/edit/…
【解决方案2】:

您可以尝试在 DataService 的构造函数中调用您的 API

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  api_url: string = "https://apiurlhere";
  categories: Object;

  constructor(private http: HttpClient) { 
    this.getCategories().subscribe(data => this.categories = data);
  }

  getCategories(){
    return this.http.get(this.api_url+'/categorylisting/?z=1');
  }

  getZones(){
    return this.http.get(this.api_url+'/zones/');
  }

}

然后就像在 Home 组件中一样获取 NavBar 组件中的类别。

  ngOnInit() {
    this.categories = this.data.categories;
  }

【讨论】:

    猜你喜欢
    • 2021-05-03
    • 2019-04-28
    • 2020-06-18
    • 2017-11-06
    • 2019-08-03
    • 2023-01-23
    • 2019-08-07
    • 1970-01-01
    • 2019-07-10
    相关资源
    最近更新 更多