diff --git a/docs/src/components/common-ui/vben-modal.md b/docs/src/components/common-ui/vben-modal.md index 1b8d7296..c795b9de 100644 --- a/docs/src/components/common-ui/vben-modal.md +++ b/docs/src/components/common-ui/vben-modal.md @@ -110,12 +110,14 @@ const [Modal, modalApi] = useVbenModal({ 以下事件,只有在 `useVbenModal({onCancel:()=>{}})` 中传入才会生效。 -| 事件名 | 描述 | 类型 | -| --- | --- | --- | -| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | -| onCancel | 点击取消按钮触发 | `()=>void` | -| onConfirm | 点击确认按钮触发 | `()=>void` | -| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | +| 事件名 | 描述 | 类型 | 版本号 | +| --- | --- | --- | --- | +| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | | +| onCancel | 点击取消按钮触发 | `()=>void` | | +| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 | +| onConfirm | 点击确认按钮触发 | `()=>void` | | +| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | | +| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.4.3 | ### Slots diff --git a/packages/@core/ui-kit/popup-ui/src/modal/__tests__/modal-api.test.ts b/packages/@core/ui-kit/popup-ui/src/modal/__tests__/modal-api.test.ts index e12b144f..9c2ef200 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/__tests__/modal-api.test.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/__tests__/modal-api.test.ts @@ -110,4 +110,19 @@ describe('modalApi', () => { expect(modalApi.store.state.title).toBe('Batch Title'); expect(modalApi.store.state.confirmText).toBe('Batch Confirm'); }); + + it('should call onClosed callback when provided', () => { + const onClosed = vi.fn(); + const modalApiWithHook = new ModalApi({ onClosed }); + modalApiWithHook.onClosed(); + expect(onClosed).toHaveBeenCalled(); + }); + + it('should call onOpened callback when provided', () => { + const onOpened = vi.fn(); + const modalApiWithHook = new ModalApi({ onOpened }); + modalApiWithHook.open(); + modalApiWithHook.onOpened(); + expect(onOpened).toHaveBeenCalled(); + }); }); diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts b/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts index 932271d8..005949e4 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts @@ -6,7 +6,12 @@ import { bindMethods, isFunction } from '@vben-core/shared/utils'; export class ModalApi { private api: Pick< ModalApiOptions, - 'onBeforeClose' | 'onCancel' | 'onConfirm' | 'onOpenChange' + | 'onBeforeClose' + | 'onCancel' + | 'onClosed' + | 'onConfirm' + | 'onOpenChange' + | 'onOpened' >; // private prevState!: ModalState; private state!: ModalState; @@ -23,8 +28,10 @@ export class ModalApi { connectedComponent: _, onBeforeClose, onCancel, + onClosed, onConfirm, onOpenChange, + onOpened, ...storeState } = options; @@ -77,8 +84,10 @@ export class ModalApi { this.api = { onBeforeClose, onCancel, + onClosed, onConfirm, onOpenChange, + onOpened, }; bindMethods(this); } @@ -115,6 +124,15 @@ export class ModalApi { } } + /** + * 弹窗关闭动画播放完毕后的回调 + */ + onClosed() { + if (!this.state.isOpen) { + this.api.onClosed?.(); + } + } + /** * 确认操作 */ @@ -122,6 +140,15 @@ export class ModalApi { this.api.onConfirm?.(); } + /** + * 弹窗打开动画播放完毕后的回调 + */ + onOpened() { + if (this.state.isOpen) { + this.api.onOpened?.(); + } + } + open() { this.store.setState((prev) => ({ ...prev, isOpen: true })); } diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal.ts b/packages/@core/ui-kit/popup-ui/src/modal/modal.ts index 360647c1..a824b98a 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal.ts @@ -139,6 +139,11 @@ export interface ModalApiOptions extends ModalState { * 点击取消按钮的回调 */ onCancel?: () => void; + /** + * 弹窗关闭动画结束的回调 + * @returns + */ + onClosed?: () => void; /** * 点击确定按钮的回调 */ @@ -149,4 +154,9 @@ export interface ModalApiOptions extends ModalState { * @returns */ onOpenChange?: (isOpen: boolean) => void; + /** + * 弹窗打开动画结束的回调 + * @returns + */ + onOpened?: () => void; } diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue index 8915dd3d..9bacb396 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue @@ -188,10 +188,12 @@ function handleFocusOutside(e: Event) { :show-close="closable" close-class="top-3" @close-auto-focus="handleFocusOutside" + @closed="() => modalApi?.onClosed()" @escape-key-down="escapeKeyDown" @focus-outside="handleFocusOutside" @interact-outside="interactOutside" @open-auto-focus="handerOpenAutoFocus" + @opened="() => modalApi?.onOpened()" @pointer-down-outside="pointerDownOutside" > (), { showClose: true }, ); -const emits = defineEmits<{ close: [] } & DialogContentEmits>(); +const emits = defineEmits< + { close: []; closed: []; opened: [] } & DialogContentEmits +>(); const delegatedProps = computed(() => { const { @@ -44,7 +46,13 @@ const delegatedProps = computed(() => { const forwarded = useForwardPropsEmits(delegatedProps, emits); const contentRef = ref | null>(null); - +function onAnimationEnd() { + if (props.open) { + emits('opened'); + } else { + emits('closed'); + } +} defineExpose({ getContentRef: () => contentRef.value, }); @@ -57,6 +65,7 @@ defineExpose({