Skip to content

Commit 0bb0d80

Browse files
committed
fix: 修复 popup 组件定位计算问题
1 parent d4a66ba commit 0bb0d80

File tree

2 files changed

+43
-19
lines changed

2 files changed

+43
-19
lines changed

src/menu/submenu.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,6 @@ export default defineComponent({
270270
);
271271
const realPopup = (
272272
<Popup
273-
popperContentElement="overlay"
274273
{...((this.popupProps ?? {}) as TdSubmenuProps['popupProps'])}
275274
overlayInnerClassName={[...this.overlayInnerClassName]}
276275
overlayClassName={[...this.overlayClassName]}

src/popup/popup.tsx

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { PropType, VNodeDirective } from 'vue';
2-
import {
3-
createPopper, Modifier, ModifierArguments, Options as popperOptions,
4-
} from '@popperjs/core';
2+
import { createPopper, ModifierArguments, Options as popperOptions } from '@popperjs/core';
53
import { debounce } from 'lodash-es';
64
import { on, off, once } from '../utils/dom';
75
import { renderTNodeJSX, renderContent } from '../utils/render-tnode';
@@ -216,6 +214,9 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
216214
return;
217215
}
218216

217+
// 获取内层 overlay 元素的尺寸,用于 flip 计算
218+
const overlayEl = this.$refs.overlay as HTMLElement;
219+
219220
const modifiers: popperOptions['modifiers'] = getIEVersion() > 9
220221
? []
221222
: [
@@ -230,25 +231,49 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
230231
},
231232
];
232233

233-
// 当使用 popperContentElement 时,添加custom modifier来维护样式
234-
if (this.popperContentElement) {
234+
// 如果没有使用 popperContentElement,则需要修正尺寸和偏移量
235+
// 因为外层 popper 元素的尺寸为 0,需要使用内层 overlay 的尺寸
236+
if (!this.popperContentElement && overlayEl) {
237+
// 在 read 阶段修改 rects.popper 的尺寸
235238
modifiers.push({
236-
name: 'applyStyles',
237-
phase: 'write',
239+
name: 'popperSize',
240+
enabled: true,
241+
phase: 'read',
238242
fn: ({ state }: { state: ModifierArguments<popperOptions>['state'] }) => {
239-
// 确保样式被应用到指定的元素
240-
const styles = state.styles.popper;
241-
if (styles && popperEl) {
242-
Object.assign(popperEl.style, styles);
243-
}
244-
const attributes = state.attributes.popper;
245-
if (attributes && popperEl) {
246-
Object.keys(attributes).forEach((key) => {
247-
popperEl.setAttribute(key, String(attributes[key]));
248-
});
243+
const overlayRect = overlayEl.getBoundingClientRect();
244+
// eslint-disable-next-line no-param-reassign
245+
state.rects.popper.width = overlayRect.width;
246+
// eslint-disable-next-line no-param-reassign
247+
state.rects.popper.height = overlayRect.height;
248+
},
249+
} as any);
250+
251+
// 在 popperOffsets 之后修正偏移量(因为 popperOffsets 用的是错误的尺寸)
252+
modifiers.push({
253+
name: 'fixPopperOffsets',
254+
enabled: true,
255+
phase: 'main',
256+
requires: ['popperOffsets'],
257+
fn: ({ state }: { state: ModifierArguments<popperOptions>['state'] }) => {
258+
const overlayRect = overlayEl.getBoundingClientRect();
259+
const { placement, modifiersData } = state;
260+
261+
if (modifiersData.popperOffsets) {
262+
// 根据 placement 修正坐标
263+
if (placement.startsWith('top')) {
264+
// top 位置需要减去内容高度
265+
// eslint-disable-next-line no-param-reassign
266+
modifiersData.popperOffsets.y -= overlayRect.height;
267+
}
268+
if (placement.startsWith('left')) {
269+
// left 位置需要减去内容宽度
270+
// eslint-disable-next-line no-param-reassign
271+
modifiersData.popperOffsets.x -= overlayRect.width;
272+
}
273+
// bottom/right 位置不需要修正
249274
}
250275
},
251-
} as unknown as any);
276+
} as any);
252277
}
253278

254279
this.popper = createPopper(triggerEl, popperEl, {

0 commit comments

Comments
 (0)