From 8f26b677f7999f73a34f2018c0c7043283459f6d Mon Sep 17 00:00:00 2001 From: Uyarn Date: Thu, 7 Dec 2023 12:02:58 +0800 Subject: [PATCH] fix(Select): pick correct option by keyboard enter --- src/select/_example/remote-search.vue | 14 +++++++------- src/select/hooks/useKeyboardControl.ts | 24 +++++++++++++++--------- src/select/hooks/useSelectOptions.ts | 2 ++ src/select/select-panel.tsx | 4 ++-- src/select/select.tsx | 4 ++-- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/select/_example/remote-search.vue b/src/select/_example/remote-search.vue index 0c243871a0..9e17809e78 100644 --- a/src/select/_example/remote-search.vue +++ b/src/select/_example/remote-search.vue @@ -4,10 +4,10 @@ v-model="value" filterable placeholder="请选择" - :on-search="remoteMethod" :loading="loading" :options="options" style="width: 200px; display: inline-block; margin: 0 20px 20px 0" + @search="remoteMethod" /> { loading.value = false; options.value = [ { - value: `${search}_test1`, - label: `${search}_test1`, + value: `腾讯_test1`, + label: `腾讯_test1`, }, { - value: `${search}_test2`, - label: `${search}_test2`, + value: `腾讯_test2`, + label: `腾讯_test2`, }, { - value: `${search}_test3`, - label: `${search}_test3`, + value: `腾讯_test3`, + label: `腾讯_test3`, }, ]; }, 500); diff --git a/src/select/hooks/useKeyboardControl.ts b/src/select/hooks/useKeyboardControl.ts index e2f3f9f59b..0e832f5ada 100644 --- a/src/select/hooks/useKeyboardControl.ts +++ b/src/select/hooks/useKeyboardControl.ts @@ -38,9 +38,9 @@ export default function useKeyboardControl({ max, }: useKeyboardControlType) { const hoverIndex = ref(-1); + const filteredOptions = ref([]); // 处理普通场景选项过滤键盘选中的问题 const virtualFilteredOptions = ref([]); // 处理虚拟滚动下选项过滤通过键盘选择的问题 const classPrefix = usePrefixClass(); - const handleKeyDown = (e: KeyboardEvent) => { const optionsListLength = displayOptions.value.length; let newIndex = hoverIndex.value; @@ -61,6 +61,7 @@ export default function useKeyboardControl({ break; case 'ArrowDown': e.preventDefault(); + if (hoverIndex.value === -1 || hoverIndex.value >= optionsListLength - 1) { newIndex = 0; } else { @@ -73,27 +74,30 @@ export default function useKeyboardControl({ break; case 'Enter': if (hoverIndex.value === -1) break; + + let finalOptions = + selectPanelRef.value.isVirtual && isFilterable.value && virtualFilteredOptions.value.length + ? virtualFilteredOptions.value + : filteredOptions.value; + + if (!finalOptions.length) finalOptions = optionsList.value; if (!innerPopupVisible.value) { setInnerPopupVisible(true, { e }); break; } - const filteredOptions = - selectPanelRef.value.isVirtual && isFilterable.value && virtualFilteredOptions.value.length - ? virtualFilteredOptions.value - : optionsList.value; if (!multiple) { - const selectedOptions = getSelectedOptions(filteredOptions[hoverIndex.value].value); - setInnerValue(filteredOptions[hoverIndex.value].value, { + const selectedOptions = getSelectedOptions(finalOptions[hoverIndex.value].value); + setInnerValue(finalOptions[hoverIndex.value].value, { option: selectedOptions?.[0], - selectedOptions: getSelectedOptions(filteredOptions[hoverIndex.value].value), + selectedOptions: getSelectedOptions(finalOptions[hoverIndex.value].value), trigger: 'check', e, }); setInnerPopupVisible(false, { e }); } else { if (hoverIndex.value === -1) return; - const optionValue = filteredOptions[hoverIndex.value]?.value; + const optionValue = finalOptions[hoverIndex.value]?.value; if (!optionValue) return; const newValue = getNewMultipleValue(innerValue.value, optionValue); @@ -119,6 +123,7 @@ export default function useKeyboardControl({ // 展开重新恢复初始值 hoverIndex.value = -1; virtualFilteredOptions.value = []; + filteredOptions.value = []; } }); @@ -140,5 +145,6 @@ export default function useKeyboardControl({ hoverIndex, handleKeyDown, virtualFilteredOptions, + filteredOptions, }; } diff --git a/src/select/hooks/useSelectOptions.ts b/src/select/hooks/useSelectOptions.ts index f85cfca737..835cda2780 100644 --- a/src/select/hooks/useSelectOptions.ts +++ b/src/select/hooks/useSelectOptions.ts @@ -106,6 +106,8 @@ export const useSelectOptions = (props: TdSelectProps, keys: Ref, inpu }); const displayOptions = computed(() => { + if (props.onSearch && props.filterable) return options.value; // 远程搜索时,不执行内部的过滤,不干预用户的自行处理,如输入首字母搜索中文的场景等 + if (!inputValue.value || !(props.filterable || isFunction(props.filter))) return options.value; const filterMethods = (option: SelectOption) => { diff --git a/src/select/select-panel.tsx b/src/select/select-panel.tsx index 4643383afb..e9f967bca0 100644 --- a/src/select/select-panel.tsx +++ b/src/select/select-panel.tsx @@ -106,8 +106,9 @@ export default defineComponent({ expose({ innerRef, - visibleData, + visibleData, // 虚拟滚动的展示数据 isVirtual, + displayOptions, // 非虚拟滚动的展示数据 }); const renderPanel = (options: SelectOption[], extraStyle?: Styles) => ( @@ -119,7 +120,6 @@ export default defineComponent({ ]} style={extraStyle} > - {} {/* create option */} {showCreateOption.value && renderCreateOption()} {/* loading状态 */} diff --git a/src/select/select.tsx b/src/select/select.tsx index 424171293b..15c6e8e92a 100644 --- a/src/select/select.tsx +++ b/src/select/select.tsx @@ -184,7 +184,7 @@ export default defineComponent({ }); }; - const { hoverIndex, virtualFilteredOptions, handleKeyDown } = useKeyboardControl({ + const { hoverIndex, virtualFilteredOptions, handleKeyDown, filteredOptions } = useKeyboardControl({ displayOptions, optionsList, innerPopupVisible, @@ -261,9 +261,9 @@ export default defineComponent({ } setInputValue(value); handleSearch(`${value}`, { e: context.e as KeyboardEvent }); - nextTick(() => { virtualFilteredOptions.value = selectPanelRef.value?.visibleData; + filteredOptions.value = selectPanelRef.value?.displayOptions; }); };