如何用defineEmits声明可被await的buttonClicked异步事件?
解决Vue子组件await emit事件的类型警告问题
要让buttonClicked事件支持await,你需要在defineEmits的类型声明里明确指定该事件的处理器返回Promise类型,具体做法如下:
修改defineEmits的类型定义
把原来基于参数数组的声明,改为用函数类型定义事件——函数的参数对应emit时传递的参数,返回值设为Promise<void>(或你业务需要的Promise类型):
const emit = defineEmits<{ buttonClicked: (buttonAction: string) => Promise<void> }>()
子组件中正常使用await
修改类型声明后,子组件里的await emit('buttonClicked', 'myAction')就不会再出现"redundant 'await' on a non-promise"的警告了:
async function handleButtonClick() { await emit('buttonClicked', 'myAction') // 这里可以写事件处理器完成后要执行的后续逻辑 }
父组件的异步处理器示例
父组件的事件处理器可以是异步函数,子组件的await会等待这个异步逻辑执行完成:
<template> <ChildComponent @buttonClicked="handleButtonAction" /> </template> <script setup lang="ts"> async function handleButtonAction(action: string) { // 模拟异步操作,比如接口请求 await new Promise(resolve => setTimeout(resolve, 1000)) console.log(`执行动作:${action}`) } </script>
原理说明
Vue的emit函数会收集所有事件处理器的返回值,如果处理器是异步函数(返回Promise),emit会返回一个Promise,等待所有处理器的Promise都resolve后才会完成。通过在defineEmits中声明事件的返回类型为Promise,TypeScript就能正确推断emit调用的返回值是Promise,从而允许安全使用await。
内容的提问来源于stack exchange,提问作者MrSpt
相关产品推荐
相关产品推荐

