diff --git a/packages/api-generator/src/locale/en/VVirtualScroll.json b/packages/api-generator/src/locale/en/VVirtualScroll.json
index e3fc6099fe0..f2529013bbe 100644
--- a/packages/api-generator/src/locale/en/VVirtualScroll.json
+++ b/packages/api-generator/src/locale/en/VVirtualScroll.json
@@ -1,7 +1,7 @@
{
"props": {
"height": "Height of the component as a css value/",
- "itemKey": "Required when using **dynamic-item-height** together with object items. Should point to a property with a unique value for each item.",
+ "itemKey": "Should point to a property with a unique value for each item, if not set then item index will be used as a key which may result in unnecessary re-renders.",
"items": "The array of items to display.",
"renderless": "Disables default component rendering functionality."
},
diff --git a/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx b/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx
index 7980fd6bede..a927163e371 100644
--- a/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx
+++ b/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx
@@ -496,7 +496,7 @@ export const VAutocomplete = genericComponent
))}
-
+
{ ({ item, index, itemRef }) => {
const itemProps = mergeProps(item.props, {
ref: itemRef,
diff --git a/packages/vuetify/src/components/VCombobox/VCombobox.tsx b/packages/vuetify/src/components/VCombobox/VCombobox.tsx
index e1921b8e3c7..3714f10fdd0 100644
--- a/packages/vuetify/src/components/VCombobox/VCombobox.tsx
+++ b/packages/vuetify/src/components/VCombobox/VCombobox.tsx
@@ -540,7 +540,7 @@ export const VCombobox = genericComponent
))}
-
+
{ ({ item, index, itemRef }) => {
const itemProps = mergeProps(item.props, {
ref: itemRef,
diff --git a/packages/vuetify/src/components/VSelect/VSelect.tsx b/packages/vuetify/src/components/VSelect/VSelect.tsx
index ad18b3bbf1f..36e59082df5 100644
--- a/packages/vuetify/src/components/VSelect/VSelect.tsx
+++ b/packages/vuetify/src/components/VSelect/VSelect.tsx
@@ -417,7 +417,7 @@ export const VSelect = genericComponent
))}
-
+
{ ({ item, index, itemRef }) => {
const itemProps = mergeProps(item.props, {
ref: itemRef,
diff --git a/packages/vuetify/src/composables/virtual.ts b/packages/vuetify/src/composables/virtual.ts
index 4b1d12dc0f1..4cc3344bce4 100644
--- a/packages/vuetify/src/composables/virtual.ts
+++ b/packages/vuetify/src/composables/virtual.ts
@@ -4,10 +4,11 @@ import { useResizeObserver } from '@/composables/resizeObserver'
// Utilities
import { computed, nextTick, onScopeDispose, ref, shallowRef, watch, watchEffect } from 'vue'
-import { clamp, debounce, IN_BROWSER, isObject, propsFactory } from '@/util'
+import { clamp, debounce, getPropertyFromItem, IN_BROWSER, propsFactory } from '@/util'
// Types
-import type { Ref } from 'vue'
+import type { PropType, Ref } from 'vue'
+import type { SelectItemKey } from '@/util'
const UP = -1
const DOWN = 1
@@ -16,8 +17,9 @@ const DOWN = 1
const BUFFER_PX = 100
type VirtualProps = {
- itemHeight?: number | string
- height?: number | string
+ itemHeight: number | string | null | undefined
+ itemKey: SelectItemKey
+ height: number | string | undefined
}
export const makeVirtualProps = propsFactory({
@@ -25,6 +27,10 @@ export const makeVirtualProps = propsFactory({
type: [Number, String],
default: null,
},
+ itemKey: {
+ type: [String, Array, Function] as PropType,
+ default: null,
+ },
height: [Number, String],
}, 'virtual')
@@ -235,11 +241,14 @@ export function useVirtual (props: VirtualProps, items: Ref) {
}
const computedItems = computed(() => {
- return items.value.slice(first.value, last.value).map((item, index) => ({
- raw: item,
- index: index + first.value,
- key: (isObject(item) && 'value' in item) ? item.value : index + first.value,
- }))
+ return items.value.slice(first.value, last.value).map((item, index) => {
+ const _index = index + first.value
+ return {
+ raw: item,
+ index: _index,
+ key: getPropertyFromItem(item, props.itemKey, _index),
+ }
+ })
})
watch(items, () => {