From ed7b6186754a1609429b6ec497ffe057931aa587 Mon Sep 17 00:00:00 2001 From: zcating Date: Fri, 12 Nov 2021 14:57:01 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fixed(dropdown):=20=E5=9C=A8=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=E6=B8=B2=E6=9F=93=E5=89=8D=EF=BC=8Corigin=20=E5=BF=85?= =?UTF-8?q?=E5=AE=9A=E4=B8=BA=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/devui/dropdown/src/dropdown-types.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/devui-vue/devui/dropdown/src/dropdown-types.ts b/packages/devui-vue/devui/dropdown/src/dropdown-types.ts index ed072b10..731d39c9 100644 --- a/packages/devui-vue/devui/dropdown/src/dropdown-types.ts +++ b/packages/devui-vue/devui/dropdown/src/dropdown-types.ts @@ -3,11 +3,9 @@ import type { PropType, ExtractPropTypes, ComponentPublicInstance } from 'vue' export type TriggerType = 'click' | 'hover' | 'manually'; export type CloseScopeArea = 'all' | 'blank' | 'none'; - export const dropdownProps = { origin: { - type: Object as PropType, - required: true + type: Object as PropType }, isOpen: { -- Gitee From d2290982cee467a701f9b09da9662c0284b706b9 Mon Sep 17 00:00:00 2001 From: zcating Date: Fri, 12 Nov 2021 14:57:50 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fixed(dropdown):=20=E5=BC=B9=E5=87=BA?= =?UTF-8?q?=E7=9A=84=E4=B8=8B=E6=8B=89=E7=AA=97=E5=8F=A3=E5=BA=94=E5=81=9A?= =?UTF-8?q?=E5=B1=85=E4=B8=AD=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/devui/dropdown/src/dropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devui-vue/devui/dropdown/src/dropdown.tsx b/packages/devui-vue/devui/dropdown/src/dropdown.tsx index 589d8c63..f741b7ed 100644 --- a/packages/devui-vue/devui/dropdown/src/dropdown.tsx +++ b/packages/devui-vue/devui/dropdown/src/dropdown.tsx @@ -27,7 +27,7 @@ export default defineComponent({ const position = { originX: 'left', originY: 'bottom', - overlayX: 'left', + overlayX: 'center', overlayY: 'top' } as const; -- Gitee From d35cd559cb64631c45382d92a68591e0793999b0 Mon Sep 17 00:00:00 2001 From: zcating Date: Fri, 12 Nov 2021 18:26:14 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor(overlay):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui/overlay/src/flexible-overlay.tsx | 117 ++++++++---------- 1 file changed, 50 insertions(+), 67 deletions(-) diff --git a/packages/devui-vue/devui/overlay/src/flexible-overlay.tsx b/packages/devui-vue/devui/overlay/src/flexible-overlay.tsx index 42556b58..90cc77de 100644 --- a/packages/devui-vue/devui/overlay/src/flexible-overlay.tsx +++ b/packages/devui-vue/devui/overlay/src/flexible-overlay.tsx @@ -1,16 +1,14 @@ import { CSSProperties, defineComponent, - getCurrentInstance, isRef, - nextTick, - onBeforeUnmount, onMounted, reactive, ref, renderSlot, toRef, watch, + computed } from 'vue'; import { CommonOverlay } from './common-overlay'; import { OriginOrDomRef, flexibleOverlayProps, FlexibleOverlayProps, Point, Origin, ConnectionPosition } from './overlay-types'; @@ -29,70 +27,47 @@ export const FlexibleOverlay = defineComponent({ // lift cycle const overlayRef = ref(null); const positionedStyle = reactive({ position: 'absolute' }); - const instance = getCurrentInstance(); onMounted(async () => { - await nextTick(); - - // 获取背景 - const overlay = overlayRef.value; - if (!overlay) { - return; - } - - // 获取原点 - const origin = getOrigin(props.origin); - if (!origin) { - return; - } - - const handleRectChange = (rect: DOMRect) => { + const handleRectChange = (position: ConnectionPosition, rect: DOMRect, origin: Origin) => { // TODO: add optimize for throttle - const point = calculatePosition(props.position, rect, origin); + const point = calculatePosition(position, rect, origin); // set the current position style's value. // the current position style is a 'ref'. positionedStyle.left = `${point.x}px`; positionedStyle.top = `${point.y}px`; }; - const handleChange = () => handleRectChange(overlay.getBoundingClientRect()); + + const locationElements = computed(() => { + // 获取面板 + const overlay = overlayRef.value; + // 获取原点 + const origin = getOrigin(props.origin); + if (!overlay || !origin) { + return; + } + return { origin, overlay }; + }); const visibleRef = toRef(props, 'visible'); const positionRef = toRef(props, 'position'); - watch(visibleRef, (visible, ov, onInvalidate) => { - if (visible) { - subscribeLayoutEvent(handleChange); - } else { - unsbscribeLayoutEvent(handleChange); + watch([locationElements, visibleRef, positionRef], async ([locationElements, visible, position], ov, onInvalidate) => { + if (!visible || !locationElements) { + return; } + const { origin, overlay } = locationElements; + handleRectChange(position, overlay.getBoundingClientRect(), origin); + const unsubscriptions = [ + subscribeLayoutEvent(() => handleRectChange(position, overlay.getBoundingClientRect(), origin)), + subscribeOverlayResize(overlay, (entries) => handleRectChange(position, entries[0].contentRect, origin)), + subscribeOriginResize(origin, () => handleRectChange(position, overlay.getBoundingClientRect(), origin)), + ]; onInvalidate(() => { - unsbscribeLayoutEvent(handleChange); + unsubscriptions.forEach(fn => fn()); }); }); - - watch([visibleRef, positionRef], () => { - handleChange(); - }); - - const resizeObserver = new ResizeObserver((entries) => { - handleRectChange(entries[0].contentRect); - }); - resizeObserver.observe(overlay as unknown as Element); - onBeforeUnmount(() => { - resizeObserver.disconnect(); - }, instance); - - if (origin instanceof Element) { - // Only when the style changing, you can change the position. - const observer = new MutationObserver(handleChange); - observer.observe(origin, { - attributeFilter: ['style'], - }); - onBeforeUnmount(() => { - observer.disconnect(); - }, instance); - } - }, instance); + }); const { backgroundClass, @@ -156,7 +131,7 @@ function getOrigin(origin: OriginOrDomRef): Origin { */ function calculatePosition( position: ConnectionPosition, - panelOrRect: HTMLElement | DOMRect, + rect: DOMRect, origin: Origin ): Point { // get overlay rect @@ -165,13 +140,6 @@ function calculatePosition( // calculate the origin point const originPoint = getOriginRelativePoint(originRect, position); - let rect: DOMRect; - if (panelOrRect instanceof HTMLElement) { - rect = panelOrRect.getBoundingClientRect(); - } else { - rect = panelOrRect; - } - // calculate the overlay anchor point return getOverlayPoint(originPoint, rect, position); } @@ -267,14 +235,29 @@ function subscribeLayoutEvent(event: (e?: Event) => void) { window.addEventListener('scroll', event, true); window.addEventListener('resize', event); window.addEventListener('orientationchange', event); + return () => { + window.removeEventListener('scroll', event, true); + window.removeEventListener('resize', event); + window.removeEventListener('orientationchange', event); + } } -/** - * 取消 layout 变化事件 - * @param event - */ -function unsbscribeLayoutEvent(event: (e?: Event) => void) { - window.removeEventListener('scroll', event, true); - window.removeEventListener('resize', event); - window.removeEventListener('orientationchange', event); +function subscribeOverlayResize(overlay: Element, callback: (entries: ResizeObserverEntry[]) => void) { + if (overlay instanceof Element) { + const resizeObserver = new ResizeObserver(callback); + resizeObserver.observe(overlay); + return () => resizeObserver.disconnect(); + } + return () => { }; +} + +function subscribeOriginResize(origin: any, callback: () => void) { + if (origin instanceof Element) { + // Only when the style changing, you can change the position. + const observer = new MutationObserver(callback); + observer.observe(origin, { attributeFilter: ['style'] }); + return () => observer.disconnect(); + } + return () => { }; } + -- Gitee From 866afd4ce5e70d9968e6022aff0e98f629de37f5 Mon Sep 17 00:00:00 2001 From: zcating Date: Fri, 12 Nov 2021 18:27:03 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(dropdown):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=B1=85=E4=B8=AD=E4=B8=8D=E6=98=BE=E7=A4=BAdropdown=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/devui-vue/devui/dropdown/src/dropdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devui-vue/devui/dropdown/src/dropdown.tsx b/packages/devui-vue/devui/dropdown/src/dropdown.tsx index f741b7ed..5dd8d6ba 100644 --- a/packages/devui-vue/devui/dropdown/src/dropdown.tsx +++ b/packages/devui-vue/devui/dropdown/src/dropdown.tsx @@ -25,7 +25,7 @@ export default defineComponent({ }, { immediate: true }); const position = { - originX: 'left', + originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top' @@ -54,7 +54,7 @@ export default defineComponent({ hasBackdrop={false} > -
+
{ctx.slots.default?.()}
-- Gitee