如何避免 re-render 分派新操作时通过循环存储 object 生成的组件

How to avoid re-render of components made by looping through store object when a new action is dispatched

抱歉,标题令人困惑,但问题很难描述得如此简短。我有一个连接到 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()),使用 | async 管道将其传递给模板并循环遍历它以呈现child 价格中每个 属性 的组成部分 object:

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>

这是可行的,因为它在 real-time 中显示 child 组件中的数据,但是我发现的问题是所有 child 组件都得到 re-rendered 每次新数据来自 WebSocket 并发送到商店时。我假设这是因为每次分派新操作时都会重建商店,所以 *NgFor 再次循环整个新的 object 并 re-renders 每个 child 组件。

我已经设法通过在同一数据切片上使用 .subscribe() 来避免这种行为,从具有新 [=21= 的组件本身的数据中构建一个新的 object ] 对于我要显示的每个 real-time 值。然后我将 object 传递给模板并对 object 中的每个单独值使用 | async 而不是整个 object。这样我就得到了预期的行为,这只是相关的 child 组件 re-rendering 而不是所有组件。我想知道如果不在组件中创建 object 而是将数据直接从商店传递到模板,是否可以实现相同的行为。

当使用ngFor时你也可以使用ngForTrackBy

A function that defines how to track changes for items in the iterable.

When items are added, moved, or removed in the iterable, the directive must re-render the appropriate DOM nodes. To minimize churn in the DOM, only nodes that have changed are re-rendered.

By default, the change detector assumes that the object instance identifies the node in the iterable. When this function is supplied, the directive uses the result of calling this function to identify the item node, rather than the identity of the object itself.

The function receives two inputs, the iteration index and the node object ID.

参考:https://angular.io/api/common/NgForOf