Я новичок в 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>
"LocalData" в useData2 управляется из изменений в useData1, в результате чего я не перезаписываю данные.
Почему я перезаписываю опору и как могу ее предотвратить?
Я думаю, что это наиболее читаемый, "декларативный" способ:
Сначала установите lodash npm я lodash
. Затем импортируйте нужную функцию, а не всю библиотеку, и инициализируйте свои данные массивом из реквизита.
<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>
@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()
Проблема, с которой вы сталкиваетесь в побочном эффекте копирования this.data
по ссылке, а не на значение.
Решение заключается в использовании техники, обычно называемой клонированием. Массивы обычно клонируются с использованием синтаксиса распространения или Array.from()
.
См. Ниже практический пример.
// Methods.
methods: {
// Use Data 1.
useData1: function() {
this.newData1 = [...this.data]
},
// Use Data 2.
useData2: function() {
this.newData2 = Array.from(this.data)
}
}