vue.js - 为什么我的 Vue 子组件一开始已经将 prop 分配给 $data,但仍然意外地改变了父 $data?

标签 vue.js vuejs2 vue-component

请参阅这个最小示例

App.vue

<template>
  <EditPerseon :previousPerson="persons[0]" />
</template>

<script>
  import EditPerseon from "./EditPerseon.vue";

  export default {
    data() {
      return {
        persons: [
          { name: "Bob", age: 18 },
          { name: "Amy", age: 20 },
        ],
      };
    },
    watch: {
      $data: {
        handler() {
          console.log("My $data have been mutated!");
        },
        deep: true,
      },
    },
    components: {
      EditPerseon,
    },
  };
</script>

EditPerseon.vue

<template>
  <input v-model="currentPerson.name" />
</template>

<script>
  export default {
    props: {
      previousPerson: Object,
    },
    data() {
      return {
        currentPerson: this.previousPerson,
      };
    },
  };
</script>

同样在 CodeSandbox 上:

https://codesandbox.io/s/why-my-vue-child-component-have-already-assign-prop-to-data-at-first-but-still-accidentaly-mutate-the-parent-data-fueuw?fontsize=14&hidenavigation=1&theme=dark

EditPerseon.vue 是我的子组件,但它仍然意外地改变了我父组件的 $data。

为什么会发生这种情况?

如何防止这种情况发生?

最佳答案

当您定义一个对象(或数组)并将其分配给 javaScript 中的另一个对象时,最终会得到对同一对象的两个引用。我想你相信你的台词:

currentPerson: this.previousPerson,

以某种方式创建一个新对象currentPerson,该对象从this.previousPerson复制值。然而,现在发生的情况是,现在您有两个不同的变量,它们都与原始对象链接:因此对 currentPerson 的更改实际上会修改父级的 person[0]

为了缓解这种情况,您可以做的一件事是在子组件中创建一个新对象:

    data() {
      return {
        currentPerson: {...this.previousPerson},
      };
    },

或者:

    data() {
      return {
        currentPerson: {
          name: this.previousPerson.name
        },
      };
    },

如果对象的某些字段本身就是对象,第一个选项将失败。第二种更安全但更冗长。您可以尝试一些像cloneDeep这样的软件包安全地克隆对象。

一个很好的通用资源,可以获取有关对象引用和副本处理的更多信息:https://javascript.info/object-copy .

除此之外,我相信观察程序处理程序总是在创建时触发,因此即使没有检测到任何更改,处理程序也会触发(但我对此 atm 不是 100% 确定)。

关于vue.js - 为什么我的 Vue 子组件一开始已经将 prop 分配给 $data,但仍然意外地改变了父 $data?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65288543/

相关文章:

javascript - VueJS 访问嵌套组件数据值

javascript - 如何使用 vuejs 和 require.ensure 处理动态组件

javascript - Firestore : Unable to fetch nested documents. 为什么?

css - 在 Vue 组件中正确使用 SASS

javascript - Vue 中的计算属性未触发监视

javascript - Vue watch[fat arrow scope] 提供了错误的 this 上下文

javascript - VueJS 不响应数组长度的变化?

vue.js - [Vue 警告] : Unknown custom element: <router-view> - did you register the component correctly?

javascript - Vue单元测试中缺少必需的 Prop 错误

javascript - 将全局变量传递给 vue 组件属性