简体   繁体   English

如何在 Vue 3 中使用带有 Composition API 和 TSX 模板的自定义事件处理程序?

[英]How to use custom event handlers in Vue 3 with Composition API and TSX templates?

I'm struggling to understand how one is supposed to work with custom events in Vue 3 with TSX templates.我很难理解应该如何使用 TSX 模板在 Vue 3 中处理自定义事件。

Consider a simple parent/child app where child sends a custom event to parent:考虑一个简单的父/子应用程序,其中子级向父级发送自定义事件:

const Child = defineComponent({
    emits: {
        boom: (x: number) => true,
    },
    setup(props, { emit }) {
        console.log("Child props", props)
        return () => (
            <div onClick={() => emit("boom", 123)}>Click me!</div>
        )
    },
})

const Parent = defineComponent(() => {
    return () => <Child onBoom={(x) => console.log(`Boom: ${x}`)} />
})

The above functions properly, and:上述功能正常,并且:

  • In child setup , props is empty (as I would expect).在 child setup中, props是空的(正如我所料)。
  • emit call in child is properly typed (it requires a number to be passed as argument).在 child 中的emit调用是正确类型的(它需要一个数字作为参数传递)。

Unfortunately, it doesn't know how to type onBoom in parent:不幸的是,它不知道如何在 parent 中键入onBoom

  Property 'onBoom' does not exist on type 'IntrinsicAttributes & Partial<{}> & Pick<Readonly<{} & {}> & VNodeProps & AllowedComponentProps & ComponentCustomProps, "style" | ... 8 more ... | "class">'.ts(2322)

Now if I add onBoom property definition to Child:现在,如果我将onBoom属性定义添加到 Child:

const Child = defineComponent({
    props: {
        onBoom: Function as PropType<(x: string) => void>,
    },
    emits: {
        boom: (x: number) => true,
    },
    ...

Then it still functions properly, and onBoom in parent becomes typed, but:然后它仍然可以正常运行,并且父级中的onBoom变成了类型,但是:

  • Developer must repeat event definitions in two places.开发人员必须在两个地方重复事件定义。
  • Nothing prevents these two definitions from going out of sync.没有什么能阻止这两个定义不同步。 In the example above, did you notice that I typed x: string instead of x: number in props.onBoom by mistake?在上面的示例中,您是否注意到我在props.onBoom中错误地输入了x: string而不是x: number
  • In child setup , props is now not empty, it is an object with onBoom property.在 child setup中, props现在不是空的,它是一个带有onBoom属性的 object。

My question is: what is the "correct" way to handle custom events with Vue 3, Composition API and TSX templates?我的问题是:使用 Vue 3、Composition API 和 TSX 模板处理自定义事件的“正确”方法是什么?

Honestly, I am tempted to disregard the whole emits / emit machinery and simply use React-style callbacks with:老实说,我很想忽略整个emits / emit机制,而只是简单地使用 React 风格的回调:

<div onClick={() => props.onBoom?.("five")}>

(What stops me at the moment is that I know that it may break when I decide to go with SSR, as these properties won't hydrate.) (此刻让我停下来的是,我知道当我决定使用 SSR 使用 go 时它可能会损坏,因为这些特性不会水合。)

In your template the emit option is available globally so you can do this在您的模板中,发出选项在全局范围内可用,因此您可以执行此操作

<button @click="$emit('onBoom')">onBoom</button>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM