#javascript #vue.js #vuetify.js #v-model
#javascript #vue.js #vuetify.js #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-model всегда добавляет еще один экземпляр, хотя ранее он уже содержал один.
Удаление this.selected;
(строка 16 в Codepen ниже) устраняет проблему.
Я подозреваю, что this.selected
это каким-то образом разыменовывает свои собственные значения, а затем не может проверить внешний вид ранее выбранных элементов.
Вот Codepen с рассматриваемой проблемой: https://codepen.io/MichaelKatz/pen/vYXXdgb
В моем реальном сценарии мне нужно фильтровать и манипулировать элементами в списке в соответствии с ранее сделанными выборками (т.е. Удалять / повторно добавлять элементы). Я делаю это, используя вычисляемое item
свойство, которое извлекает свое содержимое из ранее выбранных элементов, из selected
v-модели, и мое текущее решение потребует от меня JSON.stringify
всех моих объектов, по сути, превращая их в строки на основе значений, чтобы держать все под контролем.
Ответ №1:
Похоже, 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))
}
Комментарии:
1. Если
this.selected
будет использоваться для фильтрации данных — это приведет к тому, что стек вызовов превысит свой максимум для списков размером более 100 или около того. Это также приведет к немедленному снижению производительности для каждого добавленного элемента и для первоначального вычисленияselectedItems
. Смотрите мое эффективное решение ниже.
Ответ №2:
Похоже, что доступ к 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;
}
}
}
Ответ №3:
С моей точки зрения, проблема в том, что вы использовали multiple
реквизит, который допускает множественный выбор.
<template v-slot="{ item, index }">
<v-list-item-group
v-model="selected"
multiple
>
Простое удаление этого решит вашу проблему.