Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 仅当对象的属性已更改时,角度更新视图_Javascript_Angular_Typescript_Asp.net Web Api_Ngrx - Fatal编程技术网

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

Javascript 仅当对象的属性已更改时,角度更新视图,javascript,angular,typescript,asp.net-web-api,ngrx,Javascript,Angular,Typescript,Asp.net Web Api,Ngrx,我在angular应用程序中每隔15秒从web api轮询一次数据。这将导致我的角材质展开面板返回其未展开的默认位置,并使网站变慢,这将给用户带来不便。如果用于更新视图的数据与视图的当前数据不同,是否有办法只更新视图 下面是我的组件的代码 //component.html <mat-expansion-panel *ngFor="let item of vehicleDetail?.histalarm" cl

我在angular应用程序中每隔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>
目前我最担心的是,当用户试图阅读详细信息时,扩展面板会不断更新。这是因为我告诉扩展面板每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;

您遇到的问题是,每次刷新数据时都要替换处于您状态的对象。这意味着NGRX将通知任何订阅者它已更改的对象的选择,这意味着Angular将重新绘制UI,因为可观察对象已发出

为了避免额外的重新绘制,您需要在reducer中评估详细信息是否已更改,然后仅在详细信息已更改时返回更新状态。要计算详细信息是否已更改,您需要对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函数来评估新实体和旧实体是否相同。库,如或您可以编写自己的特定检查,了解刷新时可能更改的属性和内容。

我们可以查看组件代码吗?您可以提供相关代码以便我们在这里帮助您吗?感谢您的回复@Raph and crueengine,它已更新。如果您想让我发布更多相关代码,请告诉我。您是否尝试过使用distinctUntilChanged运算符?看看这个。这可能会有帮助,你可以发布你的NGRX reducer的代码,更新从API接收到的数据到状态吗?非常感谢你的回复!时间戳将始终更新,因此每个对象都将不同于前一个对象。有什么办法让我绕过这件事吗?因为我想不断地更新时间戳。或者这是不可能的,因为这两个属性属于同一个对象?如果您希望在显示时更新时间戳,显然您必须更新对象,并且无法避免重画。如果您不关心时间戳,则可以在执行reduce时将其从vehicledetail对象中删除(例如,
delete vehicledetail.timestamp
reduce
回调的返回行之前)。另一个选项是将“上次更新的时间戳”分解到不同的树中,并单独选择,因此,如果时间戳更改,但其他细节没有更改,则可以为细节保留相同的对象@maac
 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
      };
    }