如何在自定义Vue组件上使用@blur、@change等事件?
解决自定义Vue组件无法使用@blur/@change事件及报错问题
问题原因
- Vue 3 强制要求组件显式声明要触发的事件,未声明的事件会抛出「Component emitted event 'xxx' but it is neither declared in the emits option...」的警告。
- 自定义组件不会自动透传内部原生输入框或子组件的事件到父组件,必须手动转发。
解决方案
1. 在自定义组件中声明要触发的事件
在callback-date-multiselect组件的脚本部分,添加emits选项,明确列出blur和change事件:
// Vue 3 组合式API <script setup> import { computed } from 'vue' const props = defineProps({ modelValue: [String, Object], // 根据业务数据类型调整 name: String, initial: [String, Object] }) // 声明组件要触发的事件 const emit = defineEmits(['update:modelValue', 'blur', 'change']) // 实现v-model双向绑定逻辑 const selected = computed({ get() { return props.modelValue }, set(val) { emit('update:modelValue', val) // 可选:值更新时自动触发change事件 emit('change', val) } }) </script> // Vue 3 选项式API <script> export default { props: ['modelValue', 'name', 'initial'], // 声明事件 emits: ['update:modelValue', 'blur', 'change'], computed: { selected: { get() { return this.modelValue }, set(val) { this.$emit('update:modelValue', val) this.$emit('change', val) } } } } </script>
2. 转发内部组件/元素的事件到父组件
修改组件模板,给内部的multiselect和input添加事件监听,将它们的blur和change事件转发给父组件:
// callback-date-multiselect.html <div> <multiselect v-if="hasOptions" v-model="selected" :options="optionsList" :name="name" :searchable="false" :allow-empty="false" :maxHeight="1000" track-by="date" label="label" placeholder="Bitte wählen" key="select" @blur="$emit('blur')" @change="$emit('change', $event)" > </multiselect> <input v-if="!hasOptions" type="text" pattern="[0-9]*" inputmode="numeric" v-model="selected" v-input-mask="'date'" v-suppress-aria-invalid key="input" :name="name" @blur="$emit('blur')" @change="$emit('change', $event)" /> </div>
说明
- 显式声明
emits是Vue 3的规范要求,避免隐式事件导致的调试困难。 - 手动转发事件确保父组件能像使用原生输入框一样监听
blur和change事件,正常触发表单验证逻辑(比如你的v$.callbackDateDay.$touch)。
内容的提问来源于stack exchange,提问作者Pazulay
相关产品推荐
相关产品推荐

