简体   繁体   English

Angular 6属性绑定不适用于多级对象

[英]Angular 6 property binding not working correctly with multi-level object

I have a new app that I am making as a pet project that one of my components is behaving wrong. 我有一个正在做的宠物项目新应用程序,说明我的组件之一出了问题。

I have a complex object that stores the information for D&D monsters. 我有一个复杂的对象,用于存储D&D怪物的信息。 The component is for a option quantity changer with plus and minus buttons the increment and decrement the quantities. 该组件用于带有加号和减号按钮的选项数量更改器,用于增加和减少数量。

When I use it for a tier 1 child (ie. monster.strength) it works correctly and will increment up to the maximum quantity, and down to the base value (but not below base) When I use it for a tier 2 child (ie. monster.speed.base) it will increment correctly, but it actually changes the basemonster value as well as the selectedmonster which prevents the decrement from working. 当我将其用于第1层孩子(即,monster.strength)时,它将正常工作,并且将递增至最大数量,并降低到基本值(但不低于基本值)。当我将其用于2层孩子时( (例如monster.speed.base),它会正确递增,但实际上它会更改basemonster值以及selectedmonster,从而阻止了递减工作。

Here's the code showing how the objects are added to the document. 这是显示如何将对象添加到文档中的代码。

<option-quantity *ngIf="mod.location === 'base'"
     [max]="90"
     [step]="5"
     [costval]="mod.cost" 
     [baseval]="baseMonster[mod.type][mod.location]" 
     [(totalcost)]="selectedMonster.cost" 
     [(optval)]="selectedMonster[mod.type][mod.location]">
 </option-quantity>

And here is the components TS file 这是组件TS文件

import { Component, Input, Output } from '@angular/core';
import { EventEmitter } from '@angular/core';

@Component({
  selector: 'option-quantity',
  templateUrl: './option-quantity.component.html',
  styleUrls: ['./option-quantity.component.css']
})
export class OptionQuantityComponent {
  @Output('optvalChange') emitter1: EventEmitter<number> = new EventEmitter<number>();
  @Output('totalcostChange') emitter2: EventEmitter<number> = new EventEmitter<number>();
  @Input('baseval') set setBaseVal(value) {
    this.base = value;
  }
  @Input('optval') set setOptValue(value) {
    this.count = value;
  }
  @Input('costval') set setCostValue(value) {
    this.cost = value;
  }
  @Input('totalcost') set setTotalCostValue(value) {
    this.totalcost = value;
  }
  @Input('step') set setStepValue(value) {
    this.step = value;
  }
  @Input('max') set setMaxValue(value) {
    this.max = value;
  }

  step = 1;
  max = 10;
  base = 0;
  count = 0;
  cost = 0;
  totalcost = 0;

  increment() {
    if (this.count < this.max) {
      this.count += this.step;
      this.totalcost += this.cost * this.step;
      this.emitter1.emit(this.count);
      this.emitter2.emit(this.totalcost);
    }
  }

  decrement() {
    if (this.count > this.base) {
      this.count -= this.step;
      this.totalcost -= this.cost * this.step;
      this.emitter1.emit(this.count);
      this.emitter2.emit(this.totalcost);
    }
  }

  onChange() {
    this.emitter2.emit(this.totalcost);
    this.emitter1.emit(this.count);
  }

}

I have verified the problem lies with the tier 2 child, since i tried moving the stats into a stats child, and the speed to the root. 我已经验证了问题出在第2层子级上,因为我尝试将统计信息移到stats子级中,并且将速度移到了根级。 Which made the stats stop working and the speed work fine. 这使得统计信息停止工作并且速度正常。 I COULD just move the speed to the root of the object, but I'd rather not. 我可以将速度移到对象的根,但是我宁愿不这样做。

The component where the values are used is the create-undead component the baseMonster is created by this function: 使用值的组件是createMondead组件,此函数创建baseMonster:

  setBase() {
    this.baseMonster = Object.assign({}, this.selectedMonster);
    this.currentSize = this.baseMonster.size;
    this.previousSize = this.baseMonster.size;
  }

The entire project can be viewed in my GitHub repo 可以在我的GitHub存储库中查看整个项目

Updates: I've tried using Object.spread instead of assign, but that didn't make any difference. 更新:我尝试使用Object.spread而不是Assign,但这没有任何区别。 If I use Object.freeze and do a deep freeze on the "baseMonster" object, that object will not change, but then the "selectedMonster" stops having its tier 2 child values update. 如果我使用Object.freeze并对“ baseMonster”对象进行深度冻结,则该对象不会更改,但是“ selectedMonster”将停止更新其第2层子值。

Any help would be greatly appreciated. 任何帮助将不胜感激。

The issue is with the way you are doing your copy: 问题与您的复制方式有关:

this.baseMonster = Object.assign({}, this.selectedMonster);

Object.assign won't do a deep copy of the object, as described here : "If the source value is a reference to an object, it only copies that reference value." Object.assign不会做对象的深层副本,描述在这里 :“如果源值是对对象的引用,它只引用值的副本。”

This answer has a simple approach for that: 这个答案有一个简单的解决方法:

clonedObj = JSON.parse(JSON.stringify(originalObj))

This other answer has a detailed explanation on the topic. 其他答案对此主题有详细说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM