首页 > 解决方案 > 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);

      });

标签: angulartypescriptrxjsngrx

解决方案


这不是一个闭包,我猜你只是在两个地方共享同一个对象,并在一个地方修改它,所以在另一个地方它也会被更新。

要解决此问题,请在将其保存到时尝试复制它this.originalValue,您可以通过切换此行来做到这一点:

this.originalValue = viewModel;

进入这个:

this.originalValue = {...viewModel};

希望有帮助。


推荐阅读