意外更新子变量

发布时间:2020-07-07 17:33

我目前正在处理包含父/子组件的页面。当我在父组件中管理子组件的变量时,我的子组件会以某种方式得到更新。 我要做什么:

  1. 我的子组件有一个“站点”变量,其中包含我需要通过API发送的所有数据
  2. 我的父组件具有一个“保存”按钮,用于将子数据发送到后端
  3. 当子组件中的“站点”发生变化时,我向父组件发出了一个事件@change
  4. @change事件包含我需要的所有数据,但不是我想要的格式
  5. 有一个函数submit()获取此数据并修改其中一个数组,以便使['foo','bar']变为此'foo,bar'
  6. 问题,当我执行步骤“ 5”时,我的子组件会更新

父组件内的子组件

<configuracoes :configuracoes="configuracoes" @change="setData"
      v-if="currentPage === 'configs'"/>

子组件发出的更改事件

this.$emit("change", this.site);

“网站”变量的重要部分

site: {
  seo: {
   keywords: [],
             ...
           },
          ...
    },

setData()函数

setData(data) {
    this.data = data;
},

submitData()函数

submitData() {
    if (this.currentPage === "configs") {

        let data = ({}, Object.assign(this.data))
        let keywords = data.seo.keywords.join(',')
        data.seo.keywords = keywords
        this.$store.dispatch("sites/updateSite", {
            empresa_id: this.user.empresa_id,
            site_id: this.siteId,
            dados: data,
        });
    }
}

如您所见,我在声明另一个变量,让数据避免更新this.site变量,但未成功

回答1

首先,您如何“复制” this.data对象存在问题。

let data = ({}, Object.assign(this.data)); // this doesn't work
console.log(data === this.data); // true

const dataCopy = Object.assign({}, this.data); // this works
console.log(dataCopy === this.data); // false

Object.assign的工作方式将所有属性复制到第一个参数中。由于您只传递了一个参数,因此它不会改变,并且仍指向同一个旧对象。


如果使用正确的方法,很可能仍然会遇到相同的问题。原因是data.seo不是原始值(数字或字符串),而是对象。

这意味着整个seo对象将被复制到新副本中。换句话说,即使dataCopy !== this.datadataCopy.seo === this.data.seo也是如此。这就是所谓的“浅拷贝”。

您要确保不要修改原始的seo对象,这里有几种方法可以实现。

let goodCopy;
const newKeywords = this.data.seo.keywords.join(',');

// use object spread syntax
goodCopy = {
    ...this.data,
    seo: {
        ...this.data.seo,
        keywords: newKeywords,
    },
};

// use Object.assign
goodCopy = Object.assign(
    {},
    this.data,
    {
        seo: Object.assign(
            {},
            this.data.seo,
            {keywords: newKeywords}),
    });

// create a copy of "seo", and then change it to your liking
const seoCopy = {...this.data.seo};
seoCopy.keywords = newKeywords;
goodCopy = Object.assign({}, this.data, {seo: seoCopy});

this.$store.dispatch('sites/updateSite', {
    empresa_id: this.user.empresa_id,
    site_id: this.siteId,
    dados: goodCopy,
});

如果您想了解复制JavaScript对象的方法,请here's a good question