diff --git a/src/_util/helper.ts b/src/_util/helper.ts index 24f7827fab..c86070d6d6 100644 --- a/src/_util/helper.ts +++ b/src/_util/helper.ts @@ -71,3 +71,20 @@ export function getPropsApiByEvent(eventName: string) { export function pxCompat(param: string | number) { return typeof param === 'number' ? `${param}px` : param; } + +/** + * 获取元素相对于容器(祖先)的偏移量 + * @param element 目标元素 + * @param container 容器元素 + * @returns 相对于容器的偏移量 + */ +export function getOffsetTopToContainer(element: HTMLElement, container: HTMLElement) { + let { offsetTop } = element; + + let current = element.offsetParent as HTMLElement; + while (current && current !== container) { + offsetTop += current.offsetTop; + current = current.offsetParent as HTMLElement; + } + return offsetTop; +} diff --git a/src/select/base/Select.tsx b/src/select/base/Select.tsx index 2ef3ebb18a..563a6d2459 100644 --- a/src/select/base/Select.tsx +++ b/src/select/base/Select.tsx @@ -14,6 +14,7 @@ import classNames from 'classnames'; import isFunction from 'lodash/isFunction'; import get from 'lodash/get'; import debounce from 'lodash/debounce'; +import { getOffsetTopToContainer } from '../../_util/helper'; import useControlled from '../../hooks/useControlled'; import { useLocaleReceiver } from '../../locale/LocalReceiver'; import useConfig from '../../hooks/useConfig'; @@ -385,12 +386,16 @@ const Select = forwardRefWithStatics( const elementBottomHeight = parseInt(paddingBottom, 10) + parseInt(marginBottom, 10); // 小于0时不需要特殊处理,会被设为0 const updateValue = - firstSelectedNode.offsetTop - + getOffsetTopToContainer(firstSelectedNode, content) - content.offsetTop - (content.clientHeight - firstSelectedNode.clientHeight) + elementBottomHeight; - // eslint-disable-next-line no-param-reassign - content.scrollTop = updateValue; + + // 通过 setTimeout 确保组件渲染完成后再设置 scrollTop + setTimeout(() => { + // eslint-disable-next-line no-param-reassign + content.scrollTop = updateValue; + }); } };