From 2959c907b681220160ebe99cce836d57ecc61235 Mon Sep 17 00:00:00 2001 From: lijiacheng Date: Thu, 6 Feb 2025 17:50:49 +0800 Subject: [PATCH] =?UTF-8?q?bugfix:=E8=8F=9C=E5=8D=95menu=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E5=B8=83=E5=B1=80=E9=83=BD=E6=94=BE=E4=B8=8D?= =?UTF-8?q?=E4=B8=8B=E6=97=B6,=E9=87=87=E7=94=A8=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=90=91=E4=B8=8A=E6=88=96=E5=90=91=E4=B8=8B=E4=B8=AD=E6=9B=B4?= =?UTF-8?q?=E9=AB=98=E7=9A=84=E5=8C=BA=E5=9F=9F=E6=9D=A5=E5=B8=83=E5=B1=80?= =?UTF-8?q?+=E6=BB=9A=E5=8A=A8=E6=9D=A1=E7=9A=84=E5=BD=A2=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/index.ts | 13 ++++++++++++- packages/core/src/utils/index.ts | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 568fcf9..97f42cc 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -113,7 +113,7 @@ export default class RightMenu { this.addEvent(window, 'resize', this.destroyMenu.bind(this)) // 页面点击时销毁菜单栏 this.addEvent(document, 'mousedown', (e) => { - const hasMenu = e['path']?.some((node: HTMLDivElement) => node === menu) + const hasMenu = (e['path'] || e.composedPath())?.some((node: HTMLDivElement) => node === menu) if (!hasMenu) this.destroyMenu() }) } @@ -278,13 +278,24 @@ export default class RightMenu { // 添加二级菜单 if (opt.children && opt.children.length) { const ul = this.renderMenu(opt.children) + const parentMouseLeaveListener = () => li.removeChild(ul) li.addEventListener('mouseenter', (e) => { li.appendChild(ul) + li.parentElement?.removeEventListener('mouseleave', parentMouseLeaveListener) layoutMenuPositionEffect(li, ul) }) li.addEventListener('mouseleave', (e: MouseEvent) => { if (!e['toElement']) return let curr = e['toElement'] + + if (li.parentElement && curr === li.parentElement && (e.offsetX < 0 || e.offsetX >= li.offsetWidth)) { + // fix 存在滚动条时,从左右两侧移入子菜单 + li.parentElement.addEventListener('mouseleave', parentMouseLeaveListener, { + once: true, + }) + return + } + while (curr) { // 如果路径里存在 ul 标签, 就不需要销毁 if (curr === ul) return diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index 5529db7..bf50f88 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -110,9 +110,24 @@ export const layoutMenuPositionEffect = ( const layoutToTop = () => { let y = baseY - // 尝试向上布局,判断菜单最顶端是否超出屏幕上边缘(视窗高度) + // 尝试向上布局,判断菜单最底端是否超出屏幕下边缘(视窗高度) if (menu.offsetHeight + y > window.innerHeight) { - y = baseY + baseH - height + const topY = baseY + baseH - height + if (topY >= 0) { + // 可以向上布局 + y = topY + return y + } + // 上下都放不下时,使用向上、向下两种方式中更高的区域+滚动条的形式 + const bottomHeight = window.innerHeight - baseY + const topHeight = baseY + baseH + const isBottom = bottomHeight > topHeight + const menuHeight = Math.max(bottomHeight, topHeight) + const menuMaxHeight = Math.floor(menuHeight - 5) + y = isBottom ? baseY : baseY + baseH - menuMaxHeight + menu.style.maxHeight = `${menuMaxHeight}px` + menu.style.overflowY = 'auto' + return y } return y }