🐛(component): [dropdown]修复 popupContainer 不适用于 vue 自身渲染的元素的问题

This commit is contained in:
sight 2022-08-25 00:43:35 +08:00
parent 08bb3c0f69
commit 7087e7f005
3 changed files with 50 additions and 6 deletions

View File

@ -0,0 +1,33 @@
<script lang="ts">
export default {
name: "TeleportWrapper",
};
</script>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
export interface TeleportWrapperProps {
to?: string;
disabled?: boolean;
}
const props = withDefaults(defineProps<TeleportWrapperProps>(), {
to: '',
disabled: false,
})
const target = ref<Element | null>(null)
onMounted(() => {
if (!props.to) return;
const el = document.querySelector(props.to)
if (el) {
target.value = el
}
})
</script>
<template>
<Teleport :to="target" :disabled="!target || disabled">
<slot></slot>
</Teleport>
</template>

View File

@ -30,6 +30,7 @@ import {
ElementScrollRect, ElementScrollRect,
DropdownContext, DropdownContext,
} from "./interface"; } from "./interface";
import TeleportWrapper from './TeleportWrapper.vue';
export type DropdownTrigger = "click" | "hover" | "focus" | "contextMenu"; export type DropdownTrigger = "click" | "hover" | "focus" | "contextMenu";
@ -52,7 +53,7 @@ export interface LayDropdownProps {
mouseLeaveDelay?: number; mouseLeaveDelay?: number;
focusDelay?: number; focusDelay?: number;
alignPoint?: boolean; alignPoint?: boolean;
popupContainer?: string | HTMLElement | undefined; popupContainer?: string | undefined;
} }
const props = withDefaults(defineProps<LayDropdownProps>(), { const props = withDefaults(defineProps<LayDropdownProps>(), {
@ -77,7 +78,7 @@ const props = withDefaults(defineProps<LayDropdownProps>(), {
}); });
const childrenRefs = new Set<Ref<HTMLElement>>(); const childrenRefs = new Set<Ref<HTMLElement>>();
const dropdownCtx = inject<DropdownContext>(dropdownInjectionKey, undefined); const dropdownCtx = inject<DropdownContext | undefined>(dropdownInjectionKey, undefined);
const dropdownRef = shallowRef<HTMLElement | undefined>(); const dropdownRef = shallowRef<HTMLElement | undefined>();
const contentRef = shallowRef<HTMLElement | undefined>(); const contentRef = shallowRef<HTMLElement | undefined>();
const contentStyle = ref<CSSProperties>({}); const contentStyle = ref<CSSProperties>({});
@ -87,8 +88,7 @@ const openState = ref(false);
const containerRef = computed(() => const containerRef = computed(() =>
props.popupContainer props.popupContainer
? // @ts-ignore ? document.querySelector<HTMLElement>(props.popupContainer) ?? document.body
document.querySelector<HTMLElement>(props.popupContainer) ?? document.body
: dropdownRef.value : dropdownRef.value
) as ComputedRef<HTMLElement>; ) as ComputedRef<HTMLElement>;
@ -612,7 +612,7 @@ defineExpose({ open, hide, toggle });
<div @click="handleClick()" @contextmenu="handleContextMenuClick"> <div @click="handleClick()" @contextmenu="handleContextMenuClick">
<slot></slot> <slot></slot>
</div> </div>
<Teleport :to="popupContainer" :disabled="!popupContainer"> <TeleportWrapper :to="popupContainer">
<dl <dl
v-if="openState" v-if="openState"
ref="contentRef" ref="contentRef"
@ -623,6 +623,6 @@ defineExpose({ open, hide, toggle });
> >
<slot name="content"></slot> <slot name="content"></slot>
</dl> </dl>
</Teleport> </TeleportWrapper>
</div> </div>
</template> </template>

View File

@ -23,6 +23,17 @@
</lay-dropdown-menu> </lay-dropdown-menu>
</template> </template>
</lay-dropdown> </lay-dropdown>
&nbsp;&nbsp;
<lay-dropdown popupContainer=".layui-body">
<lay-button type="primary">下拉菜单</lay-button>
<template #content>
<lay-dropdown-menu>
<lay-dropdown-menu-item>选项一</lay-dropdown-menu-item>
<lay-dropdown-menu-item>选项二</lay-dropdown-menu-item>
<lay-dropdown-menu-item>选项三</lay-dropdown-menu-item>
</lay-dropdown-menu>
</template>
</lay-dropdown>
</template> </template>
<script> <script>