2017-07-31 82 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,它不是深度克隆,它是淺的克隆 –