From 99be68c530e4d73830fdcd0940c4450c978ba934 Mon Sep 17 00:00:00 2001 From: Wesley <985189328@qq.com> Date: Tue, 29 Jul 2025 00:55:14 +0800 Subject: [PATCH 1/4] fix: select kb hover --- .../select/components/select-panel.tsx | 69 ++++++++++--------- .../select/hooks/useKeyboardControl.ts | 12 ++-- .../select/hooks/useSelectOptions.ts | 13 ++++ packages/components/select/select.tsx | 4 +- 4 files changed, 58 insertions(+), 40 deletions(-) diff --git a/packages/components/select/components/select-panel.tsx b/packages/components/select/components/select-panel.tsx index 69f111505d..5362f75515 100644 --- a/packages/components/select/components/select-panel.tsx +++ b/packages/components/select/components/select-panel.tsx @@ -61,40 +61,45 @@ export default defineComponent({ // 递归render options const renderOptionsContent = (options: SelectOption[]) => { - return ( - + ); + }; + return renderOptions(options); }; const dropdownInnerSize = computed(() => { return { diff --git a/packages/components/select/hooks/useKeyboardControl.ts b/packages/components/select/hooks/useKeyboardControl.ts index 9728804a0b..7b882e8acd 100644 --- a/packages/components/select/hooks/useKeyboardControl.ts +++ b/packages/components/select/hooks/useKeyboardControl.ts @@ -3,12 +3,12 @@ import { usePrefixClass } from '@tdesign/shared-hooks'; import { getNewMultipleValue } from '../utils'; -import type { SelectOption, TdOptionProps, SelectValue } from '../type'; +import type { TdOptionProps, SelectValue } from '../type'; import type { ChangeHandler } from '@tdesign/shared-hooks'; import type { PopupVisibleChangeContext } from '../../popup'; export type useKeyboardControlType = { - displayOptions: ComputedRef; + totalOptions: ComputedRef; optionsList: ComputedRef; innerPopupVisible: Ref; setInnerPopupVisible: ChangeHandler; @@ -27,7 +27,7 @@ export type useKeyboardControlType = { // 统一处理键盘控制的hooks export function useKeyboardControl({ - displayOptions, + totalOptions, optionsList, innerPopupVisible, setInnerPopupVisible, @@ -48,15 +48,15 @@ export function useKeyboardControl({ const virtualFilteredOptions = ref([]); // 处理虚拟滚动下选项过滤通过键盘选择的问题 const classPrefix = usePrefixClass(); const handleKeyDown = (e: KeyboardEvent) => { - const optionsListLength = displayOptions.value.length; + const optionsListLength = totalOptions.value; let newIndex = hoverIndex.value; switch (e.code) { case 'ArrowUp': e.preventDefault(); if (hoverIndex.value === -1) { newIndex = 0; - } else if (hoverIndex.value === 0 || hoverIndex.value > displayOptions.value.length - 1) { - newIndex = optionsListLength - 1; + } else if (hoverIndex.value === 0 || hoverIndex.value > totalOptions.value - 1) { + newIndex = totalOptions.value - 1; } else { newIndex--; } diff --git a/packages/components/select/hooks/useSelectOptions.ts b/packages/components/select/hooks/useSelectOptions.ts index 1df09c7b88..4f29851d81 100644 --- a/packages/components/select/hooks/useSelectOptions.ts +++ b/packages/components/select/hooks/useSelectOptions.ts @@ -173,6 +173,18 @@ export const useSelectOptions = ( return res.length && checkAllOption ? [checkAllOption, ...res] : res; }); + // 获取总计的option数量,包括children + const totalOptions = computed(() => { + let total = 0; + total += options.value.length; + options.value.forEach((option: SelectOptionGroup) => { + if (option?.children) { + total += option.children.length; + } + }); + return total; + }); + return { options, optionsMap, @@ -181,5 +193,6 @@ export const useSelectOptions = ( displayOptions, filterMethods, searchDisplayOptions, + totalOptions, }; }; diff --git a/packages/components/select/select.tsx b/packages/components/select/select.tsx index 6b4f573269..155de84669 100644 --- a/packages/components/select/select.tsx +++ b/packages/components/select/select.tsx @@ -79,7 +79,7 @@ export default defineComponent({ return orgValue.value; }); - const { optionsMap, optionsList, optionsCache, displayOptions, filterMethods, searchDisplayOptions } = + const { optionsMap, optionsList, optionsCache, displayOptions, filterMethods, searchDisplayOptions, totalOptions } = useSelectOptions(props, keys, innerInputValue, innerValue); const setInnerValue: TdSelectProps['onChange'] = (newVal: SelectValue | SelectValue[], context) => { @@ -319,7 +319,7 @@ export default defineComponent({ }); const { hoverIndex, virtualFilteredOptions, handleKeyDown, filteredOptions } = useKeyboardControl({ - displayOptions, + totalOptions, optionsList, innerPopupVisible, setInnerPopupVisible, From 1b4b7a1145d2cec044995ca21b5f3f9a415aa0a8 Mon Sep 17 00:00:00 2001 From: Wesley <985189328@qq.com> Date: Tue, 29 Jul 2025 18:25:41 +0800 Subject: [PATCH 2/4] fix: group index --- packages/components/select/hooks/useSelectOptions.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/components/select/hooks/useSelectOptions.ts b/packages/components/select/hooks/useSelectOptions.ts index 4f29851d81..339b5de074 100644 --- a/packages/components/select/hooks/useSelectOptions.ts +++ b/packages/components/select/hooks/useSelectOptions.ts @@ -173,13 +173,14 @@ export const useSelectOptions = ( return res.length && checkAllOption ? [checkAllOption, ...res] : res; }); - // 获取总计的option数量,包括children + // 获取总计的option数量,包括children项 const totalOptions = computed(() => { let total = 0; - total += options.value.length; options.value.forEach((option: SelectOptionGroup) => { if (option?.children) { total += option.children.length; + } else { + total++; } }); return total; From cbd61ba2c89e0828fe463a1678cc781dda12cf30 Mon Sep 17 00:00:00 2001 From: Wesley <985189328@qq.com> Date: Wed, 30 Jul 2025 20:59:13 +0800 Subject: [PATCH 3/4] chore: optimize --- .../components/select/hooks/useKeyboardControl.ts | 11 +++++------ .../components/select/hooks/useSelectOptions.ts | 4 ++-- packages/components/select/select.tsx | 13 ++++++++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/components/select/hooks/useKeyboardControl.ts b/packages/components/select/hooks/useKeyboardControl.ts index 7b882e8acd..a58682e5f9 100644 --- a/packages/components/select/hooks/useKeyboardControl.ts +++ b/packages/components/select/hooks/useKeyboardControl.ts @@ -8,7 +8,7 @@ import type { ChangeHandler } from '@tdesign/shared-hooks'; import type { PopupVisibleChangeContext } from '../../popup'; export type useKeyboardControlType = { - totalOptions: ComputedRef; + optionsListLength: ComputedRef; optionsList: ComputedRef; innerPopupVisible: Ref; setInnerPopupVisible: ChangeHandler; @@ -27,7 +27,7 @@ export type useKeyboardControlType = { // 统一处理键盘控制的hooks export function useKeyboardControl({ - totalOptions, + optionsListLength, optionsList, innerPopupVisible, setInnerPopupVisible, @@ -48,15 +48,14 @@ export function useKeyboardControl({ const virtualFilteredOptions = ref([]); // 处理虚拟滚动下选项过滤通过键盘选择的问题 const classPrefix = usePrefixClass(); const handleKeyDown = (e: KeyboardEvent) => { - const optionsListLength = totalOptions.value; let newIndex = hoverIndex.value; switch (e.code) { case 'ArrowUp': e.preventDefault(); if (hoverIndex.value === -1) { newIndex = 0; - } else if (hoverIndex.value === 0 || hoverIndex.value > totalOptions.value - 1) { - newIndex = totalOptions.value - 1; + } else if (hoverIndex.value === 0 || hoverIndex.value > optionsListLength.value - 1) { + newIndex = optionsListLength.value - 1; } else { newIndex--; } @@ -68,7 +67,7 @@ export function useKeyboardControl({ case 'ArrowDown': e.preventDefault(); - if (hoverIndex.value === -1 || hoverIndex.value >= optionsListLength - 1) { + if (hoverIndex.value === -1 || hoverIndex.value >= optionsListLength.value - 1) { newIndex = 0; } else { newIndex++; diff --git a/packages/components/select/hooks/useSelectOptions.ts b/packages/components/select/hooks/useSelectOptions.ts index 339b5de074..ce03444452 100644 --- a/packages/components/select/hooks/useSelectOptions.ts +++ b/packages/components/select/hooks/useSelectOptions.ts @@ -174,7 +174,7 @@ export const useSelectOptions = ( }); // 获取总计的option数量,包括children项 - const totalOptions = computed(() => { + const optionsListLength = computed(() => { let total = 0; options.value.forEach((option: SelectOptionGroup) => { if (option?.children) { @@ -194,6 +194,6 @@ export const useSelectOptions = ( displayOptions, filterMethods, searchDisplayOptions, - totalOptions, + optionsListLength, }; }; diff --git a/packages/components/select/select.tsx b/packages/components/select/select.tsx index 155de84669..2b94b598fc 100644 --- a/packages/components/select/select.tsx +++ b/packages/components/select/select.tsx @@ -79,8 +79,15 @@ export default defineComponent({ return orgValue.value; }); - const { optionsMap, optionsList, optionsCache, displayOptions, filterMethods, searchDisplayOptions, totalOptions } = - useSelectOptions(props, keys, innerInputValue, innerValue); + const { + optionsMap, + optionsList, + optionsCache, + displayOptions, + filterMethods, + searchDisplayOptions, + optionsListLength, + } = useSelectOptions(props, keys, innerInputValue, innerValue); const setInnerValue: TdSelectProps['onChange'] = (newVal: SelectValue | SelectValue[], context) => { if (isObjectType.value) { @@ -319,7 +326,7 @@ export default defineComponent({ }); const { hoverIndex, virtualFilteredOptions, handleKeyDown, filteredOptions } = useKeyboardControl({ - totalOptions, + optionsListLength, optionsList, innerPopupVisible, setInnerPopupVisible, From 4c82da2576a878c007a5bca0deb08abe03fd7acd Mon Sep 17 00:00:00 2001 From: Wesley <985189328@qq.com> Date: Mon, 4 Aug 2025 01:21:33 +0800 Subject: [PATCH 4/4] chore: merge develop --- .../select/components/select-panel.tsx | 46 +++++-------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/packages/components/select/components/select-panel.tsx b/packages/components/select/components/select-panel.tsx index 0991e864c0..2369ebc2f4 100644 --- a/packages/components/select/components/select-panel.tsx +++ b/packages/components/select/components/select-panel.tsx @@ -64,41 +64,19 @@ export default defineComponent({ // 递归render options const renderOptionsContent = (options: SelectOption[]) => { let globalIndex = 0; - const renderOptions = (items: SelectOption[]) => { - return ( -
    - {items.map((item: SelectOptionGroup & TdOptionProps & { slots: Slots } & { $index: number }) => { - if (item.children) { - return ( - - {renderOptions(item.children)} - - ); - } - const currentIndex = globalIndex++; + return ( +
      + {options.map((item: SelectOptionGroup & TdOptionProps & { slots: Slots } & { $index: number }) => { + if (item.children) { return ( -