【问题标题】:Prevent prop from overwriting the data防止 prop 覆盖数据
【发布时间】:2019-04-03 07:34:35
【问题描述】:

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

在我的一个路由器视图组件中,我在多个函数中使用了这个数组,用 'this.data' 引用它,并将它保存在一个新变量中的函数中,这样我就不会覆盖实际的 prop 数据。

但是函数会覆盖原始的道具数据并操作道具的数据。

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

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 中的更改进行操作的,因此我不会覆盖 data 属性。

为什么我要覆盖 prop 以及如何防止它?

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案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)
      }
    
    }
    

    【讨论】:

      【解决方案2】:

      @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()

      【讨论】:

        【解决方案3】:

        我认为这是最易读的“声明式”方式:

        首先,安装 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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-05-29
          • 1970-01-01
          • 1970-01-01
          • 2018-06-27
          • 2019-12-03
          • 1970-01-01
          • 2023-03-30
          相关资源
          最近更新 更多