防止道具覆盖数据

时间:2018-10-30 09:37:32

标签: javascript vue.js vuejs2

我是vue.js的新手,并在以下情况中苦苦挣扎。 我通过道具将充满对象的数组发送到路由器视图。

在我的一个路由器视图组件中,我将该数组用于多个函数中,并用'this.data'引用它,并将其安全地放在函数中的新变量中,这样我就不会覆盖实际的道具数据。

但是这些函数会覆盖原始道具数据并操纵道具数据。

这是我的问题的一个抽象示例:

App.vue

<template>
  <div>
    <router-view :data='data'></router-view>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      data: [],
    };
  },

  created: function() {
    this.getData();
  },

  methods: {
    getData: function() {
      this.data = // array of objects
    },
  }

路由组件:

<script>
export default {

  props: {
    data: Array,
  },

  data: function() {
    return {
      newData1 = [],
      newData2 = [],
    }
  }

  created: function() {
    this.useData1();
    this.useData2();
  },

  methods: {
    useData1: function() {
      let localData = this.data;
      // do something with 'localData'
      this.newData1 = localData;
    }

    useData2: function() {
      let localData = this.data;
      // do something with 'localData'
      this.newData2 = localData;
    }
  }
}
</script>

useData2中的“ localData”是通过useData1中的更改​​来操纵的,因此我不会覆盖数据道具。

为什么我要覆盖道具,如何防止它?

3 个答案:

答案 0 :(得分:1)

您遇到的问题是通过引用而不是值来复制this.data

解决方案是使用一种通常称为克隆的技术。通常可以使用spread syntaxArray.from()克隆数组。

请参见下面的实际示例。

// Methods.
methods: {

  // Use Data 1.
  useData1: function() {
    this.newData1 = [...this.data]
  },

  // Use Data 2.
  useData2: function() {
    this.newData2 = Array.from(this.data)
  }

}

答案 1 :(得分:1)

  

@Arman Charan的回答正确。对象和数组不是原始类型,而是引用。

这里有一个很棒的视频说明=> JavaScript - Reference vs Primitive Values/ Types

因此对于引用类型,您首先必须将其克隆到另一个变量上,然后再修改此变量,而所做的更改不会影响原始数据。

但是对于嵌套的数组和高级对象,spead和Array.from将不起作用。

如果您使用的是Lodash,则可以使用_.cloneDeep()安全地克隆数组或对象。

我喜欢函数式编程,并且强烈建议使用Lodash。

因此您可以这样做:

let original_reference_type = [{ id:1 }, { id: 2 }]
let clone_original = _.cloneDeep(original_reference_type)

clone_original[0].id = "updated"
console.log(original_reference_type) //[{ id:1 }, { id: 2 }] => will not change
console.log(clone_original) // [{ id: "updated" }, { id: 2 }]

建议:对于简单的数组和对象,请使用:

对象:

let clone_original_data = {...original_data}

let clone_original_data = Object.assign({}, original_data)

数组:

let clone_original_data = [...original_data]

let clonse_original_data = original_data.slice()

对于复杂且高度嵌套的数组或对象,请使用Lodash的_.cloneDeep()

答案 2 :(得分:0)

我认为这是最容易理解的“声明式”方式:

首先,安装lodash npm i lodash。然后导入所需的函数,而不是整个库,然后使用props中的数组初始化数据。

<script>
  import cloneDeep from 'lodash/cloneDeep'

  export default {
    props: {
      data: Array
    },

    data () {
      return {
        // initialize once / non reactive
        newData1: cloneDeep(this.data),
        newData2: cloneDeep(this.data)
      }
    }
  }
</script>