You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Composable无法获取emit事件:确认弹窗onCancel无响应求助

问题

调用Composable生成确认弹窗时,组件实例已正常挂载,但无法通过onCancel获取emit事件。需求是每次需要确认交互时调用该弹窗,相关代码如下:

useModalConfirm.ts

function confirm(props: ModalConfirmProps) {
        const container = document.createElement('div');
        document.body.appendChild(container);
        const component = createVNode(ModalConfirm, {
            ...props,

            // 此处无法触发 :(
            onCancel: () => {
                console.log('canceled')
            }
        });
        render(component, container);
        return component.component;
    }

ModalConfirm.vue

<script lang="ts" setup>
import {NButton} from "naive-ui";

const emits = defineEmits(["onConfirm", "onCancel"]);

export type ModalConfirmProps = {
  title: string;
  message: string;
  confirmButtonText: string,
  cancelButtonText: string,
};

const props = defineProps<ModalConfirmProps>();
const confirm = () => {
  emits("onConfirm");
};

const cancel = () => {
  emits("onCancel");
};
</script>

<template>
  <div class="ModalConfirm">
    <div class="ModalConfirmContent">
      {{ props.title }}
      {{ props.message }}

      <NButton @click="cancel" type="error">{{ props.cancelButtonText }}</NButton>
      <NButton @click="confirm" type="success">{{ props.confirmButtonText }}</NButton>
    </div>
  </div>
</template>

解决思路

  • 修正事件名匹配问题:Vue 3中,defineEmits声明的事件名与父组件传递的回调命名需要遵循规范。你当前在子组件里声明的是onCancel/onConfirm事件,但Vue会自动将父组件传递的onXxx格式回调映射为监听xxx事件,导致两者不匹配。

    修改ModalConfirm.vue的事件声明与触发逻辑:

    // 改成不带on前缀的事件名
    const emits = defineEmits(["confirm", "cancel"]);
    
    const confirm = () => {
      emits("confirm");
    };
    
    const cancel = () => {
      emits("cancel");
    };
    

    这样父组件中传递的onCancel/onConfirm就能正确监听子组件触发的cancel/confirm事件。

  • 补充Props类型定义:当前ModalConfirmProps未包含事件回调的类型,需要补充以避免类型报错:

    export type ModalConfirmProps = {
      title: string;
      message: string;
      confirmButtonText: string;
      cancelButtonText: string;
      onConfirm?: () => void;
      onCancel?: () => void;
    };
    
  • 添加DOM清理逻辑:弹窗关闭后记得移除容器元素,避免内存泄漏,可在事件回调中补充:

    onCancel: () => {
        console.log('canceled');
        render(null, container);
        document.body.removeChild(container);
    }
    

内容的提问来源于stack exchange,提问作者npl85

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:56:54