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 <cszhjh@gmail.com>
This commit is contained in:
Rainbow
2025-11-20 15:09:16 +08:00
committed by GitHub
parent 3243b71e37
commit 439c0b5b88
4 changed files with 107 additions and 11 deletions

View File

@@ -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)
})
})

View File

@@ -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
}
}
}

View File

@@ -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(
`<el-select
v-model="value"
clearable
multiple
>
<el-option
v-for="item in options"
:label="item.label"
:key="item.value"
:value="item.value"
/>
</el-select>`,
() => ({
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(
`

View File

@@ -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 = () => {