Call emits with return result
What problem does this feature solve?
It would be nice if emits('custom-emit') returned a result, so we don't need to create an extra key in props.
What does the proposed API look like?
ParentComponent.vue
<script setup lang="ts">
import ChildComponent from '@/components/ChildComponent.vue'
const onClickChildComponent = (value: string) => value + ' world!'
</script>
<template>
<div>
<ChildComponent @custom-emit="onClickChildComponent" />`
</div>
</template>
ChildComponent.vue
<script setup lang="ts">
const emits = defineEmits<{
(e: 'custom-emit', value: string): string
}>()
console.log(emits('custom-emit', 'Hello')) // ==> 'Hello world'
</script>
<template>
<div></div>
</template>
Id argue that you are then no longer emitting an event, really. Emitting an event means the child is not concerned with what happens with the emitted value.
If your component does depends on the return value, defining that as a prop is fine and the way to go.
Id argue that you are then no longer wmittinf an event, really. Emittinf an event means the child is not concerned with what happens with the emitted value.
If your component does depwnd on the return value, defining that as a prop is fine and the way to go.
What if I have a lot of paragraphs in the child component, when selecting using Selection one of the paragraphs is sent to the parent component that has business logic.
How can I find out which paraph has changed using props?
If I put this business logic in a child component, then I have to create many similar components as a child or pre-create all types of logic in the child component.
And why do we have in defineEmits return type if emits always return void?
If you need a result from the handler then use defineProps
instead of defineEmits
And why do we have in defineEmits return type if emits always return void?
You don't need to, you can use the syntax that doesn't require providing a return type (see Vue docs for details)
If you need a result from the handler then use
defineProps
instead ofdefineEmits
And why do we have in defineEmits return type if emits always return void?
You don't need to, you can use the syntax that doesn't require providing a return type (see Vue docs for details)
Yes, but we can specify the return type. And if we can, then we can expect this type.
I agree with this issue
At the very least, defineEmits
have to be updated, because it seems to reflect the return value of the event executor.
Here is a repro
https://stackblitz.com/edit/nuxt-starter-h7hy96?file=components%2FEmitMe.vue,app.vue,tsconfig.json
However, I think it would be better if the developer is allowed to return from an event handler. SortableJs does this
我认为你真的不再发布事件了。发布事件意味着子进程不关心发布的值会发生什么。
如果你的组件确实依赖于返回值,那么将其定义为 prop 就可以了。
比如我渲染一个树形结构数据,使用递归去渲染组件A,在组件A里面有一个删除按钮,我在点击这个删除时,默认是直接删除。
但是我现在想让父组件决定到底删不删,于是我emit一个事件出去,父组件定义回调,并在回调用弹出一个弹框,请问是否确认删除,确认返回true,否返回false。
在子组件中优先判断父组件是否注册了这个回调,如果没有,则执行默认逻辑。如果有,则根据父组件的返回值执行相关逻辑,接收到true,执行默认逻辑,接收到false,执行不删除。
IMO, the focus of emitting event is more on decoupling. It is used to notify the outside world of internal state changes, but it does not care much about the external responses. DOM events do have a restricted mechanism for controlling subsequent behavior (e.g. stopPropagation
, preventDefault
, etc.), but we don't have such a unified event model in Vue. If a component wants to control internal behavior or state flow through external logic, it's recommended to use a function prop to yield a portion of the logic to external control.