【问题标题】:Angular2 - Cloning a variable to not modify sourceAngular2 - 克隆变量以不修改源
【发布时间】:2017-07-31 17:49:48
【问题描述】:

我有一个组件在订阅页面上显示一些数据。

我正在尝试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; 以某种方式更新原始数据 (payload) 有关。

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

【问题讨论】:

  • 并不是真正的重复,因为他不是在询问如何克隆,而是因为他的代码中的错误是因为在引用方面如何处理对象。两者都导致相同的答案

标签: angular typescript


【解决方案1】:

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

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

首先,简单,有点hacky并且要小心使用,因为不会涵盖所有内容:

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 的库)。

【讨论】:

  • 我接受了您的lodash 建议,并使用this.modifiedData = _.cloneDeep(this.payload); 作为我的解决方案。
  • 也会采用这种方式,但不想只建议使用库:)。很高兴我能帮上忙。
【解决方案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;

正在分配参考。因此,对原始文件的任何更改也会更改“副本”。

【讨论】:

  • 这对formData的突变没有影响
  • 用这种方法进行深度克隆不会有一些问题吗?
  • @lexith,不是深克隆,是浅克隆
  • 谢谢。是的。所以这不是非常可取的。
  • 这真的取决于你在做什么。如果您正在做一些简单的事情,那么它就可以工作。我已经在我的几个编辑功能中使用它来跟踪“之前”的值,并且效果很好。
猜你喜欢
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 2017-06-22
  • 1970-01-01
  • 2021-08-30
  • 2016-11-09
  • 1970-01-01
  • 2011-10-10
相关资源
最近更新 更多