问题描述
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模板中看到它们?
解决方法
利用角度变化检测
您可以尝试一下。
.subscribe(addressArray =>
addressArray.foreach(
address => this.addresses.push(address)
)
);
或者这个:
.subscribe(addressArray => {
for (const address of addressArray){
address => this.addresses.push(address);
}
});
这两种方法不适用于角度变化检测,因为它们是对现有阵列进行突变而不是创建新阵列。
这些方法都可以创建新的阵列,并且角度变化检测将很容易发现时间。
此:
.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>
这是合理的额外工作量。那为什么要打扰呢?
- 灵活性:现在,任意数量的方法都可以更新您的地址,并且它们都将由
scan
以统一的方式进行管理。 - 可维护性:如果您以后想更改或格式化地址,可以在一个简单的地方进行。
- 可扩展性:您可以添加
debounce
之类的RxJS运算符,以控制结果在屏幕上的显示方式。这是一种在事件排队时停止显示卡住的好方法。 - 性能:如果您的应用程序依赖于推送数据而不是绑定数据,则可以完全关闭angular的变化检测并提高应用程序的性能:)。
即使您不打算关闭变更检测,也可以在内存中对大型数组进行突变,而不必担心变更检测是否会占用它,或者无需明确告知变更检测以检查阵列的内容,变化。
,您可以尝试一下。
.subscribe(address => this.addresses = [...address,...this.addresses]);