
在 nuxt 2 的 composition api 中,子组件通过 `emit` 触发自定义事件后,父组件必须显式绑定对应事件监听器(如 `@search`),否则事件将无法被捕获——这是最常见的通信失效原因。
在 Vue 和 Nuxt 2 的 Composition API 中,emit 是子组件向父组件传递数据的核心机制,但它不会自动被父组件监听——必须通过模板中的 v-on(即 @event-name)语法显式注册监听器。你遇到的问题根源正是父组件
✅ 正确用法如下:
父组件(完整可运行示例):
<template>
<div>
<SearchBar placeholder="text3" @search="search" />
</div>
</template>
<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'
import { SearchBar } from '~/components'
export default defineComponent({
components: { SearchBar },
setup() {
const search = (value: string): void => {
console.log('Received search query:', value)
alert(`Searching for: ${value}`)
// ✅ 此处 now reliably triggered
}
return { search }
},
})
</script>子组件(关键点已优化):
<template>
<div class="search-bar-wrapper">
<input
:placeholder="placeholder"
type="text"
class="input"
@input="onInputAction($event.target.value)"
/>
@@##@@
</div>
</template>
<script>
import { defineComponent } from '@nuxtjs/composition-api'
export default defineComponent({
props: {
placeholder: {
type: String,
default: ''
}
},
emits: ['search'], // ✅ 显式声明 emit 事件(Vue 3 风格,Nuxt 2 + @nuxtjs/composition-api 支持)
setup(_, { emit }) {
const searchImage = '/icons/search.svg'
const onInputAction = (value: string) => {
// ✅ 确保非空时才 emit,避免频繁触发
if (value?.trim()) {
emit('search', value.trim())
}
}
return {
onInputAction,
searchImage
}
}
})
</script>⚠️ 注意事项:
-
Nuxt 2 需启用 Composition API 插件:确保已安装并配置 @nuxtjs/composition-api,并在 nuxt.config.js 中添加:
buildModules: ['@nuxtjs/composition-api/module']
- emits 选项虽非强制(不写也能工作),但强烈建议显式声明,它提供类型提示、开发时校验,并提升代码可维护性。
- @input 在搜索场景中可能过于频繁,生产环境推荐改用 @change 或防抖 @input(配合 lodash.debounce)。
- 若使用 TypeScript,可在 setup 中为 emit 添加类型约束(需配合 defineEmits 类型辅助,但 Nuxt 2 中更推荐升级至 Nuxt 3 以获得完整 TS 支持)。
总结:emit 只是“发送”,而 @event 才是“接收”。二者缺一不可——就像寄信需要写收件人地址,光写信不填地址,信永远到不了。










