2017-07-31 80 views
5

我有一个组件在订阅的页面上显示一些数据。Angular2 - 克隆变量以不修改源

我正在尝试clone该变量并对其进行更改,而不会影响用于呈现页面视图的原始数据。

import { UtilsService } from '../shared'; 
import { Component, Input, OnInit } from '@angular/core'; 

@Component({ 
    selector: 'app-review', 
    templateUrl: './review.component.html', 
    styleUrls: ['./review.component.css'] 
}) 
export class ReviewComponent implements OnInit { 

    @Input() payload: any = null; 

    // Object of strings that are used for the details 
    langStr: any = { 
     noDepartment: 'No Department Change', 
     noSegment: 'No Segment Change', 
     noMarket: 'No Budget Market Change', 
     noIncentive: 'No Incentive Plan Change', 
     noRole: 'No Role Change', 
     noProductionDate: 'No Production Date Change', 
     noLanguage: 'No Language Change', 
     noShift: 'No Shift Change', 
     noSupervisor: 'No Supervisor Change' 
    }; 

    // Used to scan through the final payload and assign default values if missing 
    optionalFields = ['budgetMarket', 
     'hierarchy', 
     'incentivePlan', 
     'primaryLanguage', 
     'secondaryLanguage', 
     'role', 
     'segment', 
     'shiftID', 
     'supervisor']; 

    modifiedData: any; 

    constructor(
     private utils: UtilsService 
    ) { 
    } 

    ngOnInit() { } 

    submitChanges() { 

     this.modifiedData = this.payload; 

     // Loop over all of the keys in our formData object 
     for (const key in this.modifiedData.formData) { 

      // Find shift by property if the key exists within our defined array 
      if (this.modifiedData.formData.hasOwnProperty(key) && this.utils.isInArray(this.optionalFields, key)) { 

       // If our object data doesnt have a value, set it to -1 
       if (!this.modifiedData.formData[key].length) { 
        this.modifiedData.formData[key] = '-1'; 
       } 

      } 

     } 

     // Send to database 
     console.log(this.modifiedData) 
    } 

} 

在上面这种情况下,我想我的认购this.payload数据设置为一个名为modifiedData新的变量。然后,我修改了该作业中的一些数据。

但是,只要我调用函数submitChanges(),我的HTML视图就会对modifiedData所做的更改进行更新,即使它未订阅该更新。

我认为这是this.modifiedData = this.payload;以某种方式更新原始数据(​​)。

有没有办法做到这一点,其中​​不会被触及。我基本上只是克隆它,并在将其提交给我的数据库调用之前进行一些更改。

+1

不是重复的,因为他没有询问如何克隆,而是因为他的代码中的错误,这是因为在引用方面如何处理对象。虽然 – lexith

回答

5

您不克隆对象。您只是将对该对象的引用分配给另一个变量。他们都指向完全相同的对象。

如果你想真正克隆你的对象,你基本上有两种选择:

首先,简单,一点点哈克,并谨慎使用,因为不是一切都将被覆盖:

this.modifiedData = JSON.parse(JSON.stringify(this.payload)); 

会给你一个基本克隆的新对象。

如果你想有一个更强大的克隆,你必须通过遍历你的对象并从头开始创建一个新的(或使用像lodash这样的库,它有方法)手动完成。刚刚完成


更新:其他答案建议this.modifiedData Object.assign({}, this.payload)this.modifiedData = {...this.payload};这是对简单,没有嵌套的对象,因为既做shallow copy不是你的对象的deep copy

因为JSON.parse(JSON.stringify(obj)会忽略对象,数组,数组和字符串以及布尔值,所以可能最好的选择仍然是手动克隆(或使用像lodash一样的库)。

+1

我用你的'lodash'建议,并使用'this.modifiedData = _.cloneDeep(this.payload);'来解决我的问题。 – SBB

+0

也会采取这种方式,但不希望只建议使用图书馆:)。很高兴我能帮上忙。 – lexith

2

使用这样的事情:

// Clone the object to retain a copy 
    this.originalProduct = Object.assign({}, value); 

或者你的情况:

this.modifiedData = Object.assign({}, this.payload); 

此副本从this.payload所有属性的值转换为对象。

此处的文档位于此处:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign并包括对“深层克隆”问题的讨论。

否则,此代码:

this.modifiedData = this.payload; 

被分配的参考。因此,对原件的任何更改都会更改“复制”。

+0

这两个都会导致相同的答案,但这对formData的变异没有影响。 –

+0

这种方法是否存在深度克隆问题? – lexith

+0

@lexith,它不是深度克隆,它是浅的克隆 –