我是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中的更改来操纵的,因此我不会覆盖数据道具。
为什么我要覆盖道具,如何防止它?
答案 0 :(得分:1)
您遇到的问题是通过引用而不是值来复制this.data
。
解决方案是使用一种通常称为克隆的技术。通常可以使用spread syntax或Array.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>