Vue 3表单组件submit事件触发两次的原因及是否为预期行为
Vue3中表单组件submit事件触发两次的原因与处理
问题现象
在Vue3中使用原生表单作为组件的顶级DOM元素时,若组件内监听@submit.prevent.stop并通过$emit('submit')通知父组件,父组件的@submit事件会被触发两次。但将表单用div包裹,或者换用非submit的自定义事件名时,该现象消失。
复现代码
const { createApp } = Vue const TestForm = { template: ` <form @submit.prevent.stop="onSubmit"> <input type="text" /> <input type="submit" value="in component" /> </form> `, props: { eventName: { type: String } }, methods: { onSubmit() { this.$emit(this.eventName) } } } createApp({ template: ` <div> <TestForm event-name="submit" @submit="() => onSubmit('with event name [submit]')" /> <TestForm event-name="other" @other="() => onSubmit('with event name [other]')" /> <blockquote> <p v-for="(log, i) in logs" :key="i">{{ log }}</p> </blockquote> <input type="button" value="clear" @click="logs = []" /> </div> `, components: { TestForm }, data: () => ({ logs: [] }), methods: { onSubmit(msg) { console.log(msg) this.logs.push(msg) } } }).mount('#app')
原因分析
这是Vue3的预期行为,核心原因是Vue的原生事件自动绑定机制:
当组件的根元素是原生DOM元素时,Vue会自动将父组件监听的原生DOM事件(如submit)代理绑定到该根元素上。此时你手动$emit('submit')又触发了一次自定义事件,最终导致两次触发:
- 第一次:Vue自动绑定的根表单元素原生
submit事件触发 - 第二次:组件方法中手动
$emit('submit')触发的自定义事件
触发该现象需同时满足两个条件:
- 表单是组件的顶级DOM元素
- 手动
$emit的事件名与原生DOM事件名重合(此处为submit)
解决方案
1. 换用自定义事件名(推荐)
将emit的事件名改为非原生事件名(如form-submit),避免和原生事件冲突:
// 组件内emit自定义事件名 this.$emit('form-submit') // 父组件监听对应事件 <TestForm @form-submit="() => onSubmit('custom event')" />
2. 禁用原生事件自动绑定
在组件中添加inheritAttrs: false,阻止Vue自动将父组件的事件/属性绑定到根元素上:
const TestForm = { inheritAttrs: false, // 禁用自动绑定 template: ` <form @submit.prevent.stop="onSubmit"> <input type="text" /> <input type="submit" value="in component" /> </form> `, methods: { onSubmit() { this.$emit('submit') } } }
3. 给表单添加非根元素包裹
将表单放在一个容器(如div)内,使组件根元素变为非表单元素,Vue就不会自动绑定submit事件到根元素上:
const TestForm = { template: ` <div> <!-- 添加包裹层 --> <form @submit.prevent.stop="onSubmit"> <input type="text" /> <input type="submit" value="in component" /> </form> </div> `, methods: { onSubmit() { this.$emit('submit') } } }
内容的提问来源于stack exchange,提问作者rekam
相关产品推荐
相关产品推荐

