angular - Angular 8:为什么每当复制它的数据更新时,我的不可观察类型就会更新?
问题描述
使用 Angular 8 和 Ngrx 8(无关,但为了完整起见),我有一个状态服务来管理我的视图模型状态。在其中,我有 viewModel$ 属性,它是一个行为主题。当服务最初获取它的数据时,viewModel$.next() 会使用新的视图模型值调用,另一个名为 originalValue 的属性也被设置为该视图模型值。这很好用。我想要发生的事情,以及我认为我已经编码的事情,是让原始值保持不变,这样如果我的用户想要恢复更改,我只需丢弃更新的视图模型并将其设置回原始值。
实际发生的是,每当我的视图模型更新时, originalValue 属性也会(错误地)更新。这令人费解,因为 originalValue 属性不是可观察的。我猜它与闭包有关,但我还不够熟练地把它弄明白。
底线问题 - 为什么会发生这种情况,我该如何解决?我怎样才能实现我想要的功能——即保留旧版本的数据,以便我可以在必要时恢复它?(您可能想知道为什么我不只是从商店中再次检索数据。我可以/可以这样做并且它会起作用,但我想了解这里出了什么问题。我还有“项目”的其他部分“需要同时还原,如果可以避免的话,我不想承担将状态模型转换为视图模型的额外时间/费用。)
以下是相关代码:
在国家服务中,
特性:
public viewModel$: BehaviorSubject<ProjectCoreViewModel>;
public viewModelLoaded$: BehaviorSubject<boolean> = new BehaviorSubject(false);
public originalValue: ProjectCoreViewModel;
public isPristine$: BehaviorSubject<boolean> = new BehaviorSubject(true);
private isInitialized = false;
数据的初始选择(通过外观从存储中检索)
public selectData() {
this.facade.getProjectCore()
.subscribe(core => this.fromStoreStateModel(core));
}
从状态模型到视图模型的转换,之后调用 updateViewModel$ 方法:
fromStoreStateModel(projectCore: ProjectCore) {
if (projectCore) {
const viewModel: ProjectCoreViewModel = {
projectId : projectCore.projectId,
studioId : this.facade.studioId,
ravelryProjectId : projectCore.ravelryProjectId,
ravelryLink : projectCore.ravelryLink,
isPrivate : false,
title : projectCore.projectTitle,
startedDate : projectCore.startedDate,
completedDate : projectCore.completedDate,
warpingMethod : projectCore.warpingMethodId,
weavingTechnique : projectCore.weavingTechniqueId,
reedId : projectCore.reedId,
loomId : projectCore.loomId,
itemCategory : projectCore.itemCategoryId,
itemQuantity : projectCore.quantity,
designName : projectCore.designName,
sourcePublicationId : projectCore.sourcePublicationId,
itemWidth : projectCore.itemWidth,
itemLength : projectCore.itemLength,
widthHeightRatio : this.getSizeRatio(projectCore),
coreNotes : projectCore.coreNotes,
sourcePublicationReference: projectCore.sourcePublicationReference,
};
this.updateViewModel$(viewModel);
}
}
updateViewModel$ 方法:
updateViewModel$(value: ProjectCoreViewModel) {
if (value) {
if (!this.viewModel$) {
if (!this.isInitialized) {
this.setOriginalValue(value);
this.viewModel$ = new BehaviorSubject(value);
this.viewModel$.pipe(
skip(1)).subscribe(model => {
console.log('changed core view model', model);
console.log('original value in state service', this.originalValue); // this has changed too!
this.isPristine$.next(false);
});
this.isInitialized = true;
}
} else {
this.isPristine$.next(false);
this.viewModel$.next(value);
}
this.setLoadedStatus(true);
} else {
this.setLoadedStatus(false);
}
}
setOriginalValue 方法:
private setOriginalValue(viewModel: ProjectCoreViewModel) {
this.originalValue = viewModel;
this.isPristine$.next(true);
}
在我的组件中,这部分更新了视图模型:
this.coreForm.valueChanges.pipe(debounceTime(1000))
.subscribe(value => {
model.title = value.name;
model.startedDate = value.startedDate;
model.completedDate = value.completedDate;
model.itemCategory = value.itemType;
model.weavingTechnique = value.weavingTechnique;
model.warpingMethod = value.warpingMethod;
model.reedId = value.reed;
model.loomId = value.loom;
model.itemQuantity = value.quantity;
model.designName = value.designName;
model.sourcePublicationId = value.designSource;
model.sourcePublicationReference = value.designSourceReference;
model.itemWidth = value.itemWidth;
model.itemLength = value.itemLength;
this.projectCoreViewModel$.next(model);
});
解决方案
这不是一个闭包,我猜你只是在两个地方共享同一个对象,并在一个地方修改它,所以在另一个地方它也会被更新。
要解决此问题,请在将其保存到时尝试复制它this.originalValue
,您可以通过切换此行来做到这一点:
this.originalValue = viewModel;
进入这个:
this.originalValue = {...viewModel};
希望有帮助。
推荐阅读
- shell - zsh - 捕获的输出中的函数参数?
- arrays - 使用 .each 在事务数组中查找最小的负数和最小的正数
- docker - 如何设置 xdebug / docker / drupal 堆栈?
- html - 如何更改应用程序的过渡动画?
- r - 根据R中的分组变量为连续天的特定序列创建ID
- postgresql - 如何使用 PostGIS 从调查记录中生成线段
- android - Android Instant App Deep Link 错误 - 只提供一个 URL
- python - 使用 Librosa 检测节拍能量,找到每个小节的第一个节拍
- r - Shiny R中条件面板的替代方案
- powershell - 有没有办法通过命令行安装 Borland Delphi 7?