我每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;
答案 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这样的库,或者您可以编写自己的特定检查,以了解刷新时可能更改的属性和内容。