抱歉,标题令人困惑,但问题很难如此简短地描述。我有一个连接到 WebSocket API 并将新数据分派到 NgRx 存储的服务,如下所示:
this.priceSocket.subscribe(
message => this.handleMessage(message),
error => console.log(error),
() => console.log("completed")
)
这是我将消息传递给的 handleMessage() 函数:
handleMessage(message) {
if (message.price) {
this.store.dispatch({type: "PRICES", payload: {product_id: message.product_id, price: message.price}})
}
}
这是我非常简单的减速器:
export function priceReducer(state: object = {prices: {}}, action: Action) {
switch (action.type) {
case "PRICES":
return {...state, prices: {...state.prices, [action.payload.product_id]: action.payload.price}};
}
}
然后,在我的一个组件中,我使用.pipe(share())
store 中的一部分数据,使用| async
管道将其传递给模板并循环遍历它以为价格对象中的每个属性呈现一个子组件:
prices = this.store.select(state => state.message ? state.message.prices : null).pipe(share());
和模板:
<div class="card-wrapper">
<app-price *ngFor="let item of prices | async | keyvalue" [priceKey]="item?.key" [priceValue]="item?.value"></app-price>
</div>
这是有效的,因为它实时显示子组件中的数据,但是我发现的问题是每次新数据来自 WebSocket 并发送到商店时,所有子组件都会重新渲染. 我认为这是因为每次调度新操作时都会重建商店,因此*NgFor
再次遍历整个新对象并重新渲染每个子组件。
我设法通过使用.subscribe()
相同的数据切片来避免这种行为,从组件本身的数据构建一个新对象,该对象BehaviorSubject
对于我想要显示的每个实时值都有一个新对象。然后我将对象传递给模板并使用对象中的| async
每个单独值而不是整个对象。这样我就得到了预期的行为,这只是相关的子组件重新渲染,而不是所有这些。我想知道是否可以实现相同的行为,而无需在组件中创建此对象,而是将数据直接从商店传递到模板。
使用时ngFor
也可以使用ngForTrackBy
定义如何跟踪可迭代项中的更改的函数。
当在可迭代对象中添加、移动或删除项目时,指令必须重新渲染适当的 DOM 节点。为了最大限度地减少 DOM 中的改动,仅重新渲染已更改的节点。
默认情况下,变更检测器假定对象实例标识了可迭代对象中的节点。当提供此函数时,指令使用调用此函数的结果来标识项目节点,而不是对象本身的标识。
该函数接收两个输入,迭代索引和节点对象 ID。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句