perf: improve destroyOnClose for VbenDrawer&VbenModal (#6051)

* fix: fix that the default value of modal destroyOnClose does not take effect

* perf: improve destroyOnClose for VbenDrawer
This commit is contained in:
ming4762 2025-04-27 11:26:50 +08:00 committed by GitHub
parent 0a9fc4e02d
commit 0cc1cb5a7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 64 additions and 11 deletions

View File

@ -52,6 +52,10 @@ export interface DrawerProps {
* *
*/ */
description?: string; description?: string;
/**
*
*/
destroyOnClose?: boolean;
/** /**
* *
* @default true * @default true
@ -143,10 +147,6 @@ export interface DrawerApiOptions extends DrawerState {
* *
*/ */
connectedComponent?: Component; connectedComponent?: Component;
/**
* 使 connectedComponent
*/
destroyOnClose?: boolean;
/** /**
* false * false
* @returns * @returns

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { DrawerProps, ExtendedDrawerApi } from './drawer'; import type { DrawerProps, ExtendedDrawerApi } from './drawer';
import { computed, provide, ref, useId, watch } from 'vue'; import { computed, provide, ref, unref, useId, watch } from 'vue';
import { import {
useIsMobile, useIsMobile,
@ -35,6 +35,7 @@ interface Props extends DrawerProps {
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
appendToMain: false, appendToMain: false,
closeIconPlacement: 'right', closeIconPlacement: 'right',
destroyOnClose: true,
drawerApi: undefined, drawerApi: undefined,
submitting: false, submitting: false,
zIndex: 1000, zIndex: 1000,
@ -63,6 +64,7 @@ const {
confirmText, confirmText,
contentClass, contentClass,
description, description,
destroyOnClose,
footer: showFooter, footer: showFooter,
footerClass, footerClass,
header: showHeader, header: showHeader,
@ -131,6 +133,29 @@ const getAppendTo = computed(() => {
? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div` ? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div`
: undefined; : undefined;
}); });
/**
* destroyOnClose功能完善
*/
//
const hasOpened = ref(false);
const isClosed = ref(true);
watch(
() => state?.value?.isOpen,
(value) => {
isClosed.value = false;
if (value && !unref(hasOpened)) {
hasOpened.value = true;
}
},
);
function handleClosed() {
isClosed.value = true;
props.drawerApi?.onClosed();
}
const getForceMount = computed(() => {
return !unref(destroyOnClose) && unref(hasOpened);
});
</script> </script>
<template> <template>
<Sheet <Sheet
@ -144,15 +169,17 @@ const getAppendTo = computed(() => {
cn('flex w-[520px] flex-col', drawerClass, { cn('flex w-[520px] flex-col', drawerClass, {
'!w-full': isMobile || placement === 'bottom' || placement === 'top', '!w-full': isMobile || placement === 'bottom' || placement === 'top',
'max-h-[100vh]': placement === 'bottom' || placement === 'top', 'max-h-[100vh]': placement === 'bottom' || placement === 'top',
hidden: isClosed,
}) })
" "
:modal="modal" :modal="modal"
:open="state?.isOpen" :open="state?.isOpen"
:side="placement" :side="placement"
:z-index="zIndex" :z-index="zIndex"
:force-mount="getForceMount"
:overlay-blur="overlayBlur" :overlay-blur="overlayBlur"
@close-auto-focus="handleFocusOutside" @close-auto-focus="handleFocusOutside"
@closed="() => drawerApi?.onClosed()" @closed="handleClosed"
@escape-key-down="escapeKeyDown" @escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside" @focus-outside="handleFocusOutside"
@interact-outside="interactOutside" @interact-outside="interactOutside"

View File

@ -21,7 +21,9 @@ import VbenDrawer from './drawer.vue';
const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT'); const USER_DRAWER_INJECT_KEY = Symbol('VBEN_DRAWER_INJECT');
const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {}; const DEFAULT_DRAWER_PROPS: Partial<DrawerProps> = {
destroyOnClose: true,
};
export function setDefaultDrawerProps(props: Partial<DrawerProps>) { export function setDefaultDrawerProps(props: Partial<DrawerProps>) {
Object.assign(DEFAULT_DRAWER_PROPS, props); Object.assign(DEFAULT_DRAWER_PROPS, props);

View File

@ -17,7 +17,9 @@ import VbenModal from './modal.vue';
const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT'); const USER_MODAL_INJECT_KEY = Symbol('VBEN_MODAL_INJECT');
const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {}; const DEFAULT_MODAL_PROPS: Partial<ModalProps> = {
destroyOnClose: true,
};
export function setDefaultModalProps(props: Partial<ModalProps>) { export function setDefaultModalProps(props: Partial<ModalProps>) {
Object.assign(DEFAULT_MODAL_PROPS, props); Object.assign(DEFAULT_MODAL_PROPS, props);
@ -86,7 +88,7 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
mergedOptions.onClosed = () => { mergedOptions.onClosed = () => {
options.onClosed?.(); options.onClosed?.();
if (options.destroyOnClose) { if (mergedOptions.destroyOnClose) {
injectData.reCreateModal?.(); injectData.reCreateModal?.();
} }
}; };

View File

@ -5,9 +5,27 @@ import { useVbenDrawer } from '@vben/common-ui';
import { Input, message } from 'ant-design-vue'; import { Input, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
const value = ref(''); const value = ref('');
const [Form] = useVbenForm({
schema: [
{
component: 'Input',
componentProps: {
placeholder: 'KeepAlive测试内部组件',
},
fieldName: 'field1',
hideLabel: true,
label: '字段1',
},
],
showDefaultActions: false,
});
const [Drawer, drawerApi] = useVbenDrawer({ const [Drawer, drawerApi] = useVbenDrawer({
destroyOnClose: false,
onCancel() { onCancel() {
drawerApi.close(); drawerApi.close();
}, },
@ -20,7 +38,11 @@ const [Drawer, drawerApi] = useVbenDrawer({
<template> <template>
<Drawer append-to-main title="基础抽屉示例" title-tooltip="标题提示内容"> <Drawer append-to-main title="基础抽屉示例" title-tooltip="标题提示内容">
<template #extra> extra </template> <template #extra> extra </template>
本抽屉指定在内容区域打开 此弹窗指定在内容区域打开并且在关闭之后弹窗内容不会被销毁
<Input v-model="value" placeholder="KeepAlive测试" /> <Input
v-model:value="value"
placeholder="KeepAlive测试:connectedComponent"
/>
<Form />
</Drawer> </Drawer>
</template> </template>