开发者问题收集

角度订阅将多个对象推送到数组

2020-11-05
8403

我正在制作一个 Angular 应用程序,并且我有一个空数组


addresses : any [] = [];


然后在单击事件之后,我启动一个 http 可观察对象来从服务器收取数据

然后我制作一个管道图来获取我想要的内容,然后我进行订阅

const URL ='some url';
onSearch() {
this.httpClient
  .get(`URL${{some data to generate the http observable}}`)
  .pipe(
    map(response => response.address),
    tap( => console.log("address array", address))    // address array [Object, Object, Object]
  )
  .subscribe(address => this.addresses = address);
}

在 html 模板中我有这个

<button (click)="onSearch()"> search address </button>

<ul *ngFor="let address of addresses">

<li>{{address.one}} - {{address.two}} - {{address.three}}</li>

</ul>

第一次单击按钮时可以看到结果,但是第二次单击按钮时

第一个结果从第二个结果中删除。

我的问题是如何将多个结果存储在一个数组中以及如何在 html 模板中看到它们?

2个回答

利用 angular 的变化检测

您可以尝试这个。

.subscribe(addressArray => 
  addressArray.foreach(
    address => this.addresses.push(address)
  )
);

或者这个:

.subscribe(addressArray => {
  for (const address of addressArray){
    address => this.addresses.push(address);
  }
});

这两种方法不适用于 angular 变化检测,因为它们正在改变现有数组,而不是创建新数组。

这两种方法都会创建新数组,并且 angular 变化检测将很容易发现。

这个:

.subscribe(addressArray =>
  this.addresses = this.addresses.concat(addressArray)
);

或者这个:

.subscribe(addressArray =>
  this.addresses = [...this.addresses, ...addressArray]
);

它们都是实现同一件事的非常相似的方法。

利用 Angular 的异步管道

这是一种非常不同的方法:直接在流中输出结果数组!

而不是像这个:

addresses: any[] = [];

您有一个 Observable 和一个 Subject ,如下所示:

newAddresses = new Subject<any[]>();
addresses = newAddresses.pipe(
    scan((acc, val) => ([...acc,...val]), [])
)

然后您的搜索会将结果直接发送到您的主题。

const URL ='some url';
onSearch() {
  this.httpClient
    .get(`URL${{some data to generate the http observable}}`)
    .subscribe(response => this.newAddresses.next(response.address));
}

现在在您的 HTML 中,您可以使用 angular 的异步管道订阅此数组

<button (click)="onSearch()"> search address </button>
<ul *ngFor="let address of addresses | async">
  <li>{{address.one}} - {{address.two}} - {{address.three}}</li>
</ul>

这是合理的额外工作量。那又何必呢?

  1. 灵活性 :现在任何数量的方法都可以更新您的地址,并且它们都将以统一的方式由 scan 进行管理。
  2. 可维护性 :如果您将来想要更改或格式化地址,有一个简单的 &一个可以做到这一点的地方。
  3. 可扩展性 :您可以添加花哨的 RxJS 操作符,例如 debounce ,以控制结果在屏幕上的显示方式。当事件排队时,这是一种非常好的方式来阻止显示卡顿。
  4. 性能 :如果您的应用程序依赖于推送数据而不是绑定数据,您可以完全关闭 angular 的变更检测并提高应用程序的性能 :)。

即使您不打算关闭变更检测,您也可以在内存中改变大量数组,而不必担心变更检测是否会发现它,或者需要明确告诉变更检测检查数组内容是否有变化。

Mrk Sef
2020-11-05

你可以试试这个。

.subscribe(address => this.addresses = [...address, ...this.addresses]);

Ramesh Shah
2020-11-05