@MilanV

VUE, как решить вопрос по странному поведению свзяывания двух свойств?

Доброго времени суток, прошу оказать содействие в решении проблемы по автоматическому связываю двух свойств.
Есть два компонента (основной и дочерний). В основном имеются два одинаковых массива объектов (использую для сравнения наличия изменений):
componentListWorksItems: [],
componentListWorksItemsForComparison: [],

Далее по каждому объекту из первого массива (componentListWorksItems) генерирую дочерний компонент:
<tr v-for="(itemWork, indexWork) in componentListWorksItems" :key="indexWork">
                            <td>
                                <work-item-component v-model="componentListWorksItems[indexWork]"
                                    @onUpdateEquipmentQuantityByMonth="handlerUpdateEquipmentQuantityByMonth(indexWork, $event)"
                                    @onChangingTotalsEquipmentItems="handlerOnChangingTotalsEquipmentItems(indexWork, $event)"
                                    @onSaveWorkItemInDatabase="handlerOnSaveWorkItemInDatabase(true,  $event)"
                                    :comparison-list-item="componentListWorksItemsForComparison[indexWork]['pivot']"
                                    :index="indexWork"
                                />
                            </td>
                        </tr>

Связывание изменений в дочернем компоненте с единицей первого массива основного компонента провожу следующим образом:
handlerOnChangingTotalsEquipmentItems(workItemIndex, {newSumEquipment, yearLaborCost}) {
this.$set(this.componentListWorksItems[workItemIndex]['pivot'], 'year_estimated_quantity', newSumEquipment);
this.$set(this.componentListWorksItems[workItemIndex]['pivot'], 'year_labor_cost', yearLaborCost);
}

Проверка для сравнения изменений в дочернем компоненте проводится следующим образом:
computed: {
        isChanged: function () {
            return JSON.stringify(this.value['pivot']) !== JSON.stringify(this.comparisonListItem);
        }

До сохранения данных на сервер все работает как положено
Сохраняю данные на сервер получаю результат (единицу объекта для вставки в массив)
Делаю вставку свежей записи в оба массива с сохранением реактивности:
updateSingleWorkItemInLocalListFromDatabase(workItemIndex, workItemData) {
            this.$set(this.componentListWorksItems[workItemIndex], 'pivot', workItemData);
            this.$set(this.componentListWorksItemsForComparison[workItemIndex], 'pivot', workItemData);
        }

После этой манипуляции начинается проблема:
При изменение данных в дочернем компоненте вместе с единицей из первого массива (componentListWorksItems) изменяется и аналогичная единица во втором массиве (componentListWorksItemsForComparison)
  • Вопрос задан
  • 76 просмотров
Решения вопроса 1
JRK_DV
@JRK_DV
Рецепты https://codepen.io/jrkdv/full/LKLXdq
После этой манипуляции начинается проблема:

полной реализации не видно, - но если предположить, что в массивы запихивается объект, то тогда делайте отдельную копию объекта для каждого массива, через тот же "JSON.stringify \ parse"

потому что в массив попадает не сам объект, а только ссылка на этот объект.
Из-за этого - изменение объекта по ссылке в одном из массиве, приводит к изменению объекта в другом массиве.
по факту один и тот же объект находится в двух массивах

upd
и геттер isChanged у вас получился слабо устойчивый к изменениям. Если в объекте поменяется порядок полей, то может быть неожиданный результат:
// два объекта с одинаковыми данными
let a = { a: 1, b: 1 }
let b = { b: 1, a: 1 }
let isChange = JSON.stringify(a) !== JSON.stringify(b);
// isChange будет равно true
// потому что строка будет отличаться из-за разной позиции свойств объекта
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@MilanV Автор вопроса
потому что в массив попадает не сам объект, а только ссылка на этот объект.

Спасибо! Дали верное направление. На текущий момент изменение расположений полей в разных массивах невозможно. Полей у объекта много, не вижу смысла следить за ними в отдельности.

Сделал так через копирование объекта:
updateSingleWorkItemInLocalListFromDatabase(workItemIndex, workItemData) {
            let workItemDataForComparison = Object.assign({}, workItemData);
            this.$set(this.componentListWorksItems[workItemIndex], 'pivot', workItemData);
            this.$set(this.componentListWorksItemsForComparison[workItemIndex], 'pivot', workItemDataForComparison);
        }


В случае обработки результатов действия массового сохранения делаю так:
updateAllWorksItemsInLocalListFromDatabase(worksItemsData) {
            let worksItemsDataForComparison = JSON.parse(JSON.stringify(worksItemsData));
            this.componentListWorksItems = worksItemsData;
            this.componentListWorksItemsForComparison = worksItemsDataForComparison;
        }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы