From 439c0b5b88eefef4d9123fc8383a95b7b0c3cebb Mon Sep 17 00:00:00 2001 From: Rainbow <1256734885@qq.com> Date: Thu, 20 Nov 2025 15:09:16 +0800 Subject: [PATCH] improvement(components): [select/select-v2] hoveringIndex stays on the most recently selected option with multiple (#22782) * improvement: hoveringIndex stays on the last selected option * improvement: update --------- Co-authored-by: rzzf --- .../select-v2/__tests__/select.test.ts | 40 ++++++++++++++ .../components/select-v2/src/useSelect.ts | 13 +++-- .../select/__tests__/select.test.ts | 53 ++++++++++++++++++- packages/components/select/src/useSelect.ts | 12 +++-- 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/packages/components/select-v2/__tests__/select.test.ts b/packages/components/select-v2/__tests__/select.test.ts index c09ded2488..6c682b39ac 100644 --- a/packages/components/select-v2/__tests__/select.test.ts +++ b/packages/components/select-v2/__tests__/select.test.ts @@ -2574,4 +2574,44 @@ describe('Select', () => { await input.trigger('click') expect(selectVm.dropdownMenuVisible).toBeTruthy() }) + + it('hoveringIndex should stay on the most recently selected option when using multiple', async () => { + const wrapper = createSelect({ + data() { + return { + multiple: true, + options: [ + { + value: 1, + label: 'option 1', + }, + { + value: 2, + label: 'option 2', + }, + { + value: 3, + label: 'option 3', + }, + { + value: 4, + label: 'option 4', + }, + { + value: 5, + label: 'option 5', + }, + ], + value: [1, 2], + } + }, + }) + + const select = wrapper.findComponent(Select) + const selectVm = select.vm as any + const input = wrapper.find('input') + + await input.trigger('click') + expect(selectVm.states.hoveringIndex).toBe(1) + }) }) diff --git a/packages/components/select-v2/src/useSelect.ts b/packages/components/select-v2/src/useSelect.ts index df149f7ec4..236eb55f93 100644 --- a/packages/components/select-v2/src/useSelect.ts +++ b/packages/components/select-v2/src/useSelect.ts @@ -760,12 +760,15 @@ const useSelect = (props: SelectV2Props, emit: SelectV2EmitFn) => { return getValueKey(getValue(item)) === getValueKey(props.modelValue) }) } else { - states.hoveringIndex = filteredOptions.value.findIndex((item) => - props.modelValue.some( - (modelValue: unknown) => - getValueKey(modelValue) === getValueKey(getValue(item)) + const length = props.modelValue.length + if (length > 0) { + const lastValue = props.modelValue[length - 1] + states.hoveringIndex = filteredOptions.value.findIndex( + (item) => getValueKey(lastValue) === getValueKey(getValue(item)) ) - ) + } else { + states.hoveringIndex = -1 + } } } diff --git a/packages/components/select/__tests__/select.test.ts b/packages/components/select/__tests__/select.test.ts index a61cf62d70..11c4f50b8b 100644 --- a/packages/components/select/__tests__/select.test.ts +++ b/packages/components/select/__tests__/select.test.ts @@ -1169,11 +1169,11 @@ describe('Select', () => { const selectVm = select.vm as any const input = select.find('input') await input.trigger('click') - expect(selectVm.states.hoveringIndex).toBe(0) - selectVm.navigateOptions('next') expect(selectVm.states.hoveringIndex).toBe(1) selectVm.navigateOptions('next') expect(selectVm.states.hoveringIndex).toBe(0) + selectVm.navigateOptions('next') + expect(selectVm.states.hoveringIndex).toBe(1) }) test('clearable', async () => { @@ -3955,6 +3955,55 @@ describe('Select', () => { expect(vm.value).toBe(1) }) + test('hoveringIndex should stay on the most recently selected option when using multiple', async () => { + wrapper = _mount( + ` + + `, + () => ({ + options: [ + { + value: 1, + label: 'Option 1', + }, + { + value: 2, + label: 'Option 2', + }, + { + value: 3, + label: 'Option 3', + }, + { + value: 4, + label: 'Option 4', + }, + { + value: 5, + label: 'Option 5', + }, + ], + value: [1, 2], + }) + ) + + const select = wrapper.findComponent({ name: 'ElSelect' }) + const selectVm = select.vm as any + const input = wrapper.find('input') + + await input.trigger('click') + expect(selectVm.states.hoveringIndex).toBe(1) + }) + test('should locate the most recently selected option when using multiple', async () => { wrapper = _mount( ` diff --git a/packages/components/select/src/useSelect.ts b/packages/components/select/src/useSelect.ts index fbd81b1166..848162e09f 100644 --- a/packages/components/select/src/useSelect.ts +++ b/packages/components/select/src/useSelect.ts @@ -455,11 +455,15 @@ export const useSelect = (props: SelectProps, emit: SelectEmits) => { } const updateHoveringIndex = () => { - states.hoveringIndex = optionsArray.value.findIndex((item) => - states.selected.some( - (selected) => getValueKey(selected) === getValueKey(item) + const length = states.selected.length + if (length > 0) { + const lastOption = states.selected[length - 1] + states.hoveringIndex = optionsArray.value.findIndex( + (item) => getValueKey(lastOption) === getValueKey(item) ) - ) + } else { + states.hoveringIndex = -1 + } } const resetSelectionWidth = () => {