Почему vuejs реплицирует данные своей v-модели, когда на v-модель ссылаются в вычисляемом свойстве?

В следующем коде:

JS

const App = {
  template: '#app-template',
  data: () => ({
    selected: [],
    items: Array.from({length: 50}, (x, i) => i+1).map(i => ({
      id: i ,
      name: `Item ${i}`,
      subtitle: `Subtitle ${i}`
    }))
  }),
  computed: {
    parsedItems() {
      this.selected;
      return this.items.map(item => ({
        someValue: 3,
        ...item
      }));
    }
  }
}


new Vue({
  vuetify: new Vuetify(),
  render: h => h(App)
}).$mount('#app')

HTML

<script type = "text/x-template" id = "app-template">
  <v-app>
    {{selected}}
    <v-container>

        <v-virtual-scroll
          :items = "parsedItems"
          :item-height = "65"
          height = "500"
        >
          <template v-slot = "{ item, index }">
           <v-list-item-group
             v-model = "selected"
             multiple
           >
            <v-list-item :key = "item.id" :value = "item">
              <v-list-item-action>
                <v-checkbox
                  :input-value = "selected.includes(item.id)"
                  color = "primary"
                />
              </v-list-item-action>
              <v-list-item-content>
                <v-list-item-title>
                  Index: {{ index }} {{ item.name }}
                </v-list-item-title>
                <v-list-item-subtitle>
                  {{ item.subtitle }}
                </v-list-item-subtitle>
              </v-list-item-content>
            </v-list-item>
           </v-list-item-group>
          </template>
        </v-virtual-scroll>
    </v-container>
  </v-app>
</script>

<div id = "app"></div>

Когда любой из флажков, которые я установил или снял, selected v-модель всегда добавляет еще один экземпляр, хотя ранее он уже содержал один.

Удаление this.selected; (строка 16 в Codepen ниже) устраняет проблему.

Я подозреваю, что this.selected каким-то образом разыменовывает свои собственные значения, а затем не может проверить внешний вид ранее выбранных элементов.

Вот Codepen с проблемой: https://codepen.io/MichaelKatz/pen/vYXXdgb

В моем реальном сценарии мне нужно фильтровать и манипулировать элементами в списке в соответствии с ранее сделанным выбором (т.е. удалять/повторно добавлять элементы). Я делаю это с помощью вычисляемого item свойства, которое извлекает свое содержимое из ранее выбранных элементов, из selected v-модели, и мое текущее решение потребует от меня JSON.stringify всех моих объектов, по сути, делая их строками на основе значений, чтобы хранить вещи. проверять.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
179
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

С моей точки зрения, проблема в том, что вы использовали реквизиты multiple, которые позволяют выбирать несколько вариантов.

      <template v-slot = "{ item, index }">
       <v-list-item-group
         v-model = "selected"
         multiple
       >

Простое удаление решит вашу проблему.

v-model не работает с объектами

<v-list-item :key = "item.id" :value = "item">    <!-- change this -->
<v-list-item :key = "item.id" :value = "item.id"> <!-- into this   -->

И создайте новое вычисляемое свойство, чтобы «гидратировать» эти идентификаторы:

selectedItems() {
  return this.selected.map(id => this.parsedItems.find(x => x.id === id))
}

Обновлен Codepen

Если this.selected будет использоваться для фильтрации данных, это приведет к тому, что стек вызовов превысит свой максимум для списков, превышающих 100 или около того. Это также приведет к немедленному снижению производительности для каждого добавленного элемента и для первоначального расчета selectedItems. См. мое эффективное решение ниже.

silicakes 13.12.2020 13:13
Ответ принят как подходящий

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

Лучшим решением, которое я смог придумать, было добавление дополнительного вычисляемого свойства, которое будет содержать логику, включающую this.selected.

Это действительно решило проблему для меня.

  computed: {
    parsedItems() {
      return this.items.map(item => ({
        someValue: 3,
        ...item
      }));
    },
    filteredItems() { // adding another computed property while using this.selected
      this.selected;
      return this.parsedItems;
    }
  }
}

Другие вопросы по теме