如何使用 <script setup> 语法在 Vue3 中从子级向父级发出事件?

agm*_*984 43 javascript vuejs3

我有以下组件:

<SomeModal :is-modal-active="isAddingThing" @close="isAddingThing = false" />
Run Code Online (Sandbox Code Playgroud)

该组件内部如下所示:

<script setup>
import { defineProps } from 'vue'

const props = defineProps({
    isModalActive: Boolean,
})

const handleClose = () => {
    emit('close') // doesn't work
}
</script>

<template>
<V-Modal @close="handleClose">
    ...
</V-Modal>
</template>
Run Code Online (Sandbox Code Playgroud)

我如何发送给父母?

McG*_*rew 59

在 Vue 3.2 版本中,如果你想从 inside 发出一个事件<script setup>,那么你所要做的就是使用defineEmits()内部自动可用的方法定义你的发出<script setup>(你不必导入它),然后你就可以发出事件通过调用emit('myEventName', myParams). 这是一些示例代码...

<script setup>
const emit = defineEmits(['eventA', 'eventB'])
function btnClick(params) {
    emit('eventA')
    emit('eventB', params)
}
</script>
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用我得到ReferenceError:emit is not Defined (3认同)

Dan*_*iel 31

2022 年更新 -Vue 3.2及更新版本

\n

和API 已弃用useContextgetCurrentInstance不再向 Vue 3 API 公开。相反,您应该defineEmits在安装脚本的根级别使用 。

\n
<template>\n  <button @click="action(\'\')"></button>\n</template>\n<script setup>\n  const emit = defineEmits([\'close\', \'unClose\'])\n  const action = (id) => emit(\'close\', val);\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

对于打字稿,定义是:

\n
const emit = defineEmits<{\n  (e: \'close\', val: string): void\n  (e: \'unClose\', id: number): void\n}>()\n
Run Code Online (Sandbox Code Playgroud)\n
\n

过时的、预Vue 3.2

\n
    \n
  • 您根本不需要定义emit 即可$emit从模板运行
  • \n
  • useContext提供在设置函数中使用的发射函数
  • \n
  • usingdefineEmits将发出列表添加到组件(相当于emits:组件的定义),但对发出没有帮助
  • \n
\n

useContextdefineEmits从 Vue 3.2 开始已弃用,请使用getCurrentInstancedefineEmits

\n
\n

useContext

\n
<template>\n  <button @click="action(\'\')"></button>\n  <!-- emit is defined through useContext -->\n  <button @click="emit(\'action1\',\'\')">1</button>\n  <!-- $emit here doesn\'t need to be defined -->\n  <button @click="$emit(\'action2\',\'\')">2</button>\n</template>\n<script setup>\n  import { defineProps, useContext } from \'vue\'\n  const { emit } = useContext()\n  const action = (id) => emit(\'action\', id);\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,vetur 扩展可能会告诉您它已被弃用,您应该使用useSlotsanduseAttrs代替。如果您想emit从脚本中使用,这些显然不会有帮助。

\n

getCurrentInstance

\n
import { defineProps, getCurrentInstance} from \'vue\'\nconst { emit } = getCurrentInstance()\n
Run Code Online (Sandbox Code Playgroud)\n

除了运行发出之外,vue3 还允许(推荐\xe2\x80\x8d\xe2\x99\x82\xef\xb8\x8f)定义发出,因此组件父组件可能知道组件可能发出哪些事件。要使用<script setup>表单执行此操作,您可以使用defineEmit

\n
<script setup>\n  import { defineEmit } from \'vue\'\n  const emit = defineEmit([\'action\'])\n  const action = (id) => emit(\'action\', id);\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

这将允许发送action发出事件,但如果您发出doit尽管它仍然会发出,您将在控制台中收到警告

\n
\n

[Vue warn]:组件发出了事件“doit”,但它既没有在发出选项中声明,也没有声明为“onDoit”属性。

\n
\n

  • `useContext` 和 `defineEmit` 现已弃用。使用“getCurrentInstance”和“defineEmits” (13认同)
  • 使用 learnvue 中的 DefineEmit 示例更新了答案 (3认同)