仅当对象的属性已更改时,角度更新视图

时间:2018-08-13 12:59:45

标签: javascript angular typescript asp.net-web-api ngrx

我每15秒钟从我的角度应用程序中的Web API轮询一次数据。这导致我的角形材质扩展面板返回到其未扩展的默认位置,并减慢了网站速度,给用户带来了不便。如果我用来更新视图的数据与视图的当前数据不同,我是否可以仅更新视图?

下面是我的组件的代码。

              //component.html

                <mat-expansion-panel *ngFor="let item of vehicleDetail?.histalarm" class="expansion-panel">
                    <mat-expansion-panel-header>
                        <p class="mobil-font-size">
                            <!-- The date is highlighted in the color of the severity of the alarm-->
                            <span [ngClass]="getDetailColors(item.severity)"> {{ item.timestamp}} </span>
                            <span style="font-weight: bold;"> - Description: </span> {{ item.description }}.
                        </p>
                    </mat-expansion-panel-header>
                    <!-- All extra info is being displayed below. Translators is used for kind and severity
                    to make them more readable-->
                    <p>
                        <span class="bold"> More Information </span>
                        <br>
                        <span class="bold"> Severity: </span> {{ severityTranslator(item.severity) }}
                        <br>
                        <span class="bold"> Details: </span> {{item.details }}
                    </p>
                </mat-expansion-panel>

在我的component.ts中,我使用ngrx存储从Web api获取我的数据。 vehicleDetail是选定的车辆,而vehicleDetail?.histalarm”用于循环显示车辆存在的警报列表。


// component.ts
ngOnInit() {
   // init vehicles details
    this.store.select(fromStore.getAllVehicleDetails).subscribe(data => {
      this.vehicleDetails = data;
      this.setMarkers(this.selected);
      this.updateFavoriteVehicles();
    });
    this.store.dispatch(new fromStore.LoadVehicleDetails());
}

目前,我最担心的是,随着用户尝试阅读详细信息,扩展面板会不断更新。发生这种情况是因为我告诉扩展面板每15秒更新一次,因为有时间戳和其他我想更新的内容。但是,不断的中断令人沮丧,这就是我要解决的问题。

编辑

根据需求发布减速器的代码

import * as fromVehicleDetails from '../actions/vehicledetails.action';
import { VehicleDetail } from '../../models/vehicle-detail';

export interface VehicleDetailsState {
  entities: { [id: number]: VehicleDetail };
  loaded: boolean;
  loading: boolean;
}

export const initialState: VehicleDetailsState = {
  entities: {},
  loaded: false,
  loading: false
};

export function reducer(
  state = initialState,
  action: fromVehicleDetails.VehicleDetailsAction
): VehicleDetailsState {
  switch (action.type) {
    case fromVehicleDetails.LOAD_VEHICLEDETAILS: {
      return {
        ...state,
        loading: true
      };
    }
    case fromVehicleDetails.LOAD_VEHICLEDETAILS_SUCCESS: {
      const vehicledetails = action.payload;
      const entities = vehicledetails.reduce(
        (
          entity: { [id: number]: VehicleDetail },
          vehicledetail: VehicleDetail
        ) => {
          return {
            ...entity,
            [vehicledetail.id]: vehicledetail
          };
        },
        {
          ...state.entities
        }
      );

      return {
        ...state,
        loaded: true,
        loading: false,
        entities
      };
    }
    case fromVehicleDetails.LOAD_VEHICLEDETAILS_FAIL: {
      return {
        ...state,
        loaded: false,
        loading: false
      };
    }
  }
  return state;
}

export const getVehicleDetailsEntities = (state: VehicleDetailsState) =>
  state.entities;
export const getVehicleDetailsLoaded = (state: VehicleDetailsState) =>
  state.loaded;
export const getVehicleDetailsLoading = (state: VehicleDetailsState) =>
  state.loading;

1 个答案:

答案 0 :(得分:2)

您遇到的问题是,每次刷新数据时都将替换状态下的对象。这意味着NGRX将通知所有订户选择该对象已更改的对象,这意味着Angular将重新绘制UI,因为已发射了可观察对象。

为避免多余的重画,您需要做的是在减速器中评估细节是否已更改,然后仅在细节已更改时才返回更新状态。要计算详细信息是否已更改,您将需要针对从API返回的数据与当前处于该状态的数据进行“深度相等”检查,例如:

 case fromVehicleDetails.LOAD_VEHICLEDETAILS_SUCCESS: {
      const vehicledetails = action.payload;
      const entities = vehicledetails.reduce(
        (
          entity: { [id: number]: VehicleDetail },
          vehicledetail: VehicleDetail
        ) => {
          return {
            ...entity,
            [vehicledetail.id]: vehicledetail
          };
        },
        {
          ...state.entities
        }
      );

      // Add logic to check if entities has changed, and not return the updated entities if they have not:
      if (deepEqual(entities, state.entities)) return { ...state, loaded: true, loading: false };

      // Entities have changed, return updated state with new entities:        
      return {
        ...state,
        loaded: true,
        loading: false,
        entities: entities
      };
    }

然后,您将需要实现deepEquals函数来评估新实体和旧实体是否相同。像lodash have operators for doing this这样的库,或者您可以编写自己的特定检查,以了解刷新时可能更改的属性和内容。