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

Vue 3 如何在可复用composable文件中正常使用emit?

Vue Composable中使用emit报错解决方案

报错原因

Property 'emit' does not exist on type 'ComponentInternalInstance | null'报错来自两个层面:

  • getCurrentInstance()的返回值类型默认为ComponentInternalInstance | null,TypeScript无法确定实例一定存在,所以直接解构emit会触发类型报错
  • 如果你在组件setup的同步执行周期外调用getCurrentInstance(),运行时会实际返回null,导致逻辑失效

解决方案

方案1:非空断言+类型声明(仅适合同步调用场景)

如果确定会在setup阶段同步调用该composable,可以直接通过类型断言指定实例非空,代码如下:

import { getCurrentInstance, ComponentInternalInstance } from 'vue'
import Swal from "sweetalert2/dist/sweetalert2.js";

export default function useModal() {
  // 显式断言实例不为空
  const { emit } = getCurrentInstance() as ComponentInternalInstance

  function myId() {
    emit('id', '123')
  }

  return {
    myId
  }
}

注意事项:

  • 必须在组件setup阶段同步调用useModal(),不可在异步回调、生命周期钩子内延迟调用该composable,否则运行时依然会抛出实例为空的错误

方案2:将emit作为参数传入composable(更推荐)

该方案是Vue官方推荐的composable最佳实践,没有调用时机限制,类型校验更安全,无需依赖当前实例:

1. 调整composable代码

import Swal from "sweetalert2/dist/sweetalert2.js";

// 接收emit作为入参,可根据实际需求自定义emit的类型声明
export default function useModal(emit: (event: 'id', payload: string) => void) {
  function myId() {
    emit('id', '123')
  }

  return {
    myId
  }
}

2. 组件内调用示例

<script setup lang="ts">
import useModal from './useGoo.ts'

// 组件内声明emit
const emit = defineEmits<{
  id: [id: string]
}>()

// 调用composable时传入当前组件的emit
const { myId } = useModal(emit)
</script>

该方案优势:

  • 不受调用时机限制,异步场景下也可以正常使用
  • TypeScript类型校验更严格,完全规避实例为空的运行时风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 02:45:04