Vue js / javascript массив объектов - как определить, был ли какой-либо из объектов изменен и какой - PullRequest
0 голосов
/ 31 декабря 2018

Я работаю над проектом Vuejs.В какой-то момент у меня есть массив объектов (данных, взятых с сервера), таких как:

[
    {
        name: "Book one",
        price: 12,
        active: true
    },
    {
        name: "Small drone X12",
        price: 54,
        active: false
    },
    {
        name: "something else",
        price: 32,
        active: true
    }
]

Данные используются для создания динамической формы на странице, чтобы пользователь мог редактировать данные.Как я могу проверить, был ли какой-либо объект изменен пользователем и какой (можно изменить один, два или любое их количество), чтобы я мог показать пользователю кнопку для обновления измененных данных.Я хотел бы обновить только данные из объектов, которые действительно были изменены, - не все из них.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Один из подходов заключается в прослушивании change событий при передаче индекса массива объекта и имени свойства для измененного поля.Затем присвойте значение другому массиву, содержащему изменения.

new Vue({
  el: '#app',
  data: () => ({
    items: [
      {
        name: "Book one",
        price: 12,
        active: true
      },
      {
        name: "Small drone X12",
        price: 54,
        active: false
      },
      {
        name: "something else",
        price: 32,
        active: true
      }
    ],
    changed: []
  }),
  mounted () {
    this.changed = Array(this.items.length).fill({})
  },
  methods: {
    onPropertyChanged (index, prop) {
      this.changed.splice(index, 1, Object.assign({}, this.changed[index], { [prop]: this.items[index][prop] }))
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="(item, index) in items" :key="index">
    <label>Name</label>
    <input v-model="item.name" @change="onPropertyChanged(index, 'name')">
    <label>Price</label>
    <input v-model="item.price" type="number" min="0" @change="onPropertyChanged(index, 'price')">
    <label>Active</label>
    <input v-model="item.active" type="checkbox" @change="onPropertyChanged(index, 'active')">
  </div>
  
  <hr/>
  
  <h4>Changes</h4>
  <pre v-for="(item, index) in changed" :key="`change-${index}`"><code>{{ item }}
0 голосов
/ 31 декабря 2018

Вы можете хранить вычисленную строку JSON объектов в отображенном массиве

const comparison = data.map(JSON.stringify); // in order string based values for direct comparison

Позже в коде вы можете сравнить с этими значениями

data.forEach((obj, index) => {
  // if they do match, skip
  if (JSON.stringify(obj) === comparison[index]) return;

  // they don't match, update comparison value
  comparison[index] = JSON.stringify(obj);

  // update VUE state and other things here
})

Таким образом, вам нужно толькообновить обновленные значения, и только когда-либо нужно рассчитать значения сравнения.Это работает, даже если объект имеет определенное обновленное поле, но все еще является тем же объектом (который прошел бы тест на равенство object === object, даже если значение обновилось).

Еще один более сложный пример вращается вокруг прокси или просмотракаждый установщик объектов запускает изменения всякий раз, когда они обновляются на месте, но на всю жизнь я все еще не понимаю прокси, верно ...

А что, если массив полей изменит размер?

Хотя это работает, если размер данных никогда не изменяется, если размер массива данных изменяется ... он все равно будет работать, поскольку в соответствующем индексе будет неопределенное значение, в результате чего сравнение строк вернет false.Однако было бы лучше добавить его в форму, а затем в конце с простой модификацией приведенного выше кода:

if (comparison[index] === undefined) {
  // add the form to the field, it'll add in order
}
// they don't match, update comparison value
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...