vuejs 复制数据对象和删除属性也会从原始对象中删除属性

Posted

技术标签:

【中文标题】vuejs 复制数据对象和删除属性也会从原始对象中删除属性【英文标题】:vuejs copying data object and removing property will remove the property from original object as well 【发布时间】:2018-06-30 00:33:08 【问题描述】:

我在 vue 中有一个看起来像这样的数据对象

rows[
0 
  title: "my title",
  post: "my post text",
  public: false,
  info: "some info"
,
1 
 title: "my title",
  post: "my post text"
  public: true,
  info: "some info"
,
2 
 title: "my title",
  post: "my post text"
  public: false,
  info: "some info"

]

然后,如果需要,我会复制该对象并删除某些属性,然后再将对象发布到我的后端,如下所示:

var postData = this.rows;
      postData.forEach(function(o) 

        if (o.public === true) 
          delete o.info;
        
      );

      var uploadData = ;
      uploadData.blogpost = postData;
      axios(
          method: 'post',
          url: myUrl,
          responseType: 'json',
          data: uploadData
        )

问题是delete o.info; 也会从我的 vm 根数据中删除该属性,我不明白为什么,因为我创建了一个新变量/将根数据复制到该变量中。那么如何在发布之前从我的数据中删除某些对象属性而不改变 vue 中的根数据 vm 呢?

【问题讨论】:

【参考方案1】:

您需要通过克隆来获取数据的副本。克隆数据的方法有很多种,推荐使用lodash的函数cloneDeep

postDataCopy = _.cloneDeep(postData)

然后你可以随意修改postDataCopy而不用修改原来的。

【讨论】:

这可能行得通,但是,这是否会使您的应用程序的大小增加 24kb Gzip?【参考方案2】:

这是因为在 javascript 中对象是通过引用复制的,这意味着尽管您正在更改 postData,它实际上是在引用保存数据的原始地址,即 rows。你可以这样做

postData = JSON.parse(JSON.stringify(rows))

【讨论】:

这对我来说非常适合嵌套对象/数组数据 这非常有效,尤其是在您不必开始安装或导入 lodash 的情况下【参考方案3】:

您需要复制引用的变量。

// ES6
let copiedObject = Object.assign(, originalObject)

【讨论】:

这只会制作对象的浅拷贝,例如,子对象保留对原始对象的引用 是的,这对我来说是一个陷阱,无法弄清楚为什么嵌套对象也没有被分配。所以这只适用于浅层对象(没有嵌套)【参考方案4】:

这是因为 row 是引用类型,而 postData 指向与 row 相同的引用。如果您的对象/数组只包含值类型(如数字、字符串、布尔值等)而不是引用类型(如对象或数组),则可以使用 Object.assign 复制而不引用(深拷贝)。如果您的 Object 包含引用类型,例如包含对象的对象,则内部复制的对象将是引用类型。

示例 1:

var user = 
name: "abc",
address: "cde"
;

var copiedUser = Object.assign(, user); 

它从用户那里复制属性。所以user和copyedUser是不同的对象,因为user只包含值类型

示例 2:

var user = 
name: "abc",
address: "cde",
other_info:  // reference type
   country: "india"


;

var copiedUser = Object.assign(, user); 

现在它从用户复制所有属性,但用户包含引用类型(对象)的 other_info。所以改变值类型的copyedUser属性不会影响用户,但改变copyedUser或用户的other_info会相互影响。

copiedUser.name ="new name"; // 不会反映在用户中

copiedUser .other_info.country = "new country"; // 也会反映在用户中

所以 Object.assign 将复制到一个级别。如果您的对象包含嵌套对象或数组,您需要迭代并复制到最后一级。

Object.assign 也接受 和 []。所以你也可以返回数组。

例如:var copiedArray= Object.assign([], [1,3,4,5]);

所以对于你的情况,我认为你需要迭代你的数组直到对象然后复制并将它们推送到另一个数组中;

var rows = [
 
  title: "my title",
  post: "my post text",
  public: false,
  info: "some info"
,

 title: "my title",
  post: "my post text",
  public: true,
  info: "some info"
,
 
 title: "my title",
  post: "my post text",
  public: false,
  info: "some info"

];

var postData = [];

for(var i=0;i<rows.length;i++) 
postData.push(Object.assign(, rows[i]));

【讨论】:

【参考方案5】:

Reactivity 是由每个对象和数组内部的 Observer _proto 引起的。

如果需要,您可以使用以下对象工具作为 mixin 从每个对象中删除 ovservable 填充。

const isEmpty = (value) =&gt; 

if (!value) return false;

if (Array.isArray(value)) return Boolean(value.length);

return value ? Boolean(Object.keys(value).length) : false;

;

const isNotEmpty = value =&gt; isEmpty(value);

const clone = (value) =&gt; 

if (!value) return value;

const isObject = (typeof value === 'object');

const isArray = Array.isArray(value);

if (!isObject &amp;&amp; !isArray) return value;

// Removing reference of Array of values

if (isArray) return [...value.map(val =&gt; clone(val))];

if (isObject) return  ...value ;

return value;

;

const merge = (parent, values) =&gt; ( ...parent, ...values );

export 

isEmpty,

isNotEmpty,

clone,

merge

;

还有商店里的吸气剂。

import  clone  from '@/utils/object';

const getData = state =&gt; clone(state.data);
export default 
   getData

【讨论】:

以上是关于vuejs 复制数据对象和删除属性也会从原始对象中删除属性的主要内容,如果未能解决你的问题,请参考以下文章

即使在删除原始属性后,通过引用复制到第二个属性的对象仍然存在?

NSManagedObjects 的深拷贝 NSMutableArray

即使使用复制构造函数,克隆对象也会更改原始对象[重复]

02-浅拷贝和深拷贝

在 MATLAB 中删除对象句柄并保留变量

VueJS构造器:new Vue({})