英文:
Vue3 - Warning Component emitted event but it is neither declared in the emits option nor as an prop
问题
你的代码中似乎存在一个问题,Vue 3的emits
选项需要在组件中声明事件,但你的组件中似乎没有声明update:modelValue
事件。这就是为什么你会收到警告消息的原因。
为了解决这个问题,你可以在你的组件中声明emits
选项并包含update:modelValue
事件,如下所示:
emits: ['update:modelValue', 'onOutsideClicked'],
这将告诉Vue你的组件会触发update:modelValue
事件,从而消除警告。
不过,请确保你的组件确实需要使用modelValue
来传递数据,因为这通常是用于支持v-model
的一个约定,如果你的组件不需要这个功能,你可以考虑不使用modelValue
来传递数据,从而避免这个警告。
英文:
I'm trying to remove some warnings for my project, which is in vue3 using vuetify3.
Currenlty I've a component that is a side dialog
<template>
<div>
<slot name="activator" :show="() => setShowDialog(true)" :close="() => setShowDialog(false)" />
<VDialog
v-model="componentData.showDialog"
@click:outside="onClickOutside"
:width="componentProperties.width"
:min-width="componentProperties.minWidth"
:max-width="componentProperties.maxWidth"
:content-class="contentClass"
persistent
transition="slide-x-reverse-transition"
>
<VCard v-show="componentData.showDialog" v-fill-parent>
<VCardTitle v-if="hasTitle" :class="componentProperties.titleClass">
<VRow justify="center" align="center">
<slot name="title">
<span v-if="componentProperties.title">{{ componentProperties.title }}</span>
</slot>
<VSpacer />
<VCol v-if="componentProperties.showTopCloseButton" cols="1">
<VBtn
@click.stop.prevent="() => setShowDialog(false)"
color="transparent"
elevation="0"
size="medium"
>
<IconifyMdiClose />
</VBtn>
</VCol>
</VRow>
</VCardTitle>
<slot name="body">
<VCardText>
<slot name="content-prepend" />
<slot>
<slot name="content" />
</slot>
<slot name="content-append" />
</VCardText>
</slot>
<VCardActions>
<slot name="actions" :show="() => setShowDialog(true)" :close="() => setShowDialog(false)" />
</VCardActions>
</VCard>
</VDialog>
</div>
</template>
<script setup lang="ts">
import { Events } from '@enums/events';
export interface IDialogConfirmComponentProperties {
modelValue?: boolean;
modelData?: any;
title?: string;
isActive?: boolean;
showTopCloseButton?: boolean;
titleClass?: string;
fillHeight?: boolean;
persistent?: boolean;
minWidth?: string | number;
maxWidth?: string | number;
width?: string | number;
}
export interface IDialogConfirmComponentEvents {
(e: 'onOutsideClicked'): void;
(e: 'update:isActive', val?: boolean): void;
(e: 'update:modelValue', visible?: boolean): void;
}
export interface IDialogConfirmComponentData {
showDialog?: boolean;
}
const componentProperties = withDefaults(defineProps<IDialogConfirmComponentProperties>(), {
persistent: false,
fillHeight: true,
modelValue: false,
isActive: true,
showTopCloseButton: false,
titleClass: 'pt-5 text-wrap',
width: 'auto',
minWidth: 650,
maxWidth: 650,
});
const componentData = reactive<IDialogConfirmComponentData>({
showDialog: false,
});
const emits = defineEmits<IDialogConfirmComponentEvents>();
const slots = useSlots();
const hasTitle = computed(() => !!slots['title'] || !!componentProperties?.title);
const contentClass = computed(() => {
return ['side-dialog', componentProperties.fillHeight ? 'fill-height' : ''].join(' ');
});
function onClickOutside(payload: MouseEvent) {
emits('onOutsideClicked');
if (componentProperties.persistent) return;
setShowDialog(false);
}
watch(
() => componentData.showDialog,
showDialog => {
componentData.showDialog = showDialog;
emitsDialogVisibleChanges();
},
);
watch(
() => componentProperties.modelValue,
showDialog => {
componentData.showDialog = showDialog;
},
);
function setShowDialog(value: boolean) {
componentData.showDialog = value;
}
function emitsDialogVisibleChanges() {
if (componentProperties.modelValue === undefined || componentProperties.modelValue === null) return;
emits('update:isActive', componentData.showDialog);
emits('update:modelValue', componentData.showDialog);
}
</script>
<style lang="css">
.side-dialog {
inset-block-start: 0 !important;
inset-inline-end: 0 !important;
}
</style>
Which then I called like:
<template>
<SideDialog title="Configurations" show-top-close-button v-model="isDialogVisible">
<template #activator="{ show }">
<VBtn :variant="componentProperties.variant" @click.stop.prevent="show">
<VIcon>mdi-cog</VIcon>
</VBtn>
</template>
<VRow justify="center" align="center">
<span>teste</span>
</VRow>
</SideDialog>
</template>
<script setup lang="ts">
import type { ButtonVariant } from '@/types/vuetify';
export interface IConfigurationComponentProperties {
variant?: ButtonVariant;
}
const componentProperties = withDefaults(defineProps<IConfigurationComponentProperties>(), {
variant: 'plain',
});
const isDialogVisible = ref(false);
</script>
But I'm currently it's always consoling a warning saying:
> component emitted event "update:modelValue" but it is neither declared in the emits option nor as an "onUpdate:modelValue" prop.
Am I missing something trivial here? I mean I'm listening to the modelValue update event.
Why is it complaining about it?
答案1
得分: 1
这个答案对Vue 3发出警告:“非emit事件侦听器过多”可能对你有帮助。
将模板包装在一个<div>
中可以解决这个警告。
<template>
<div>
<slot
...
</VDialog>
</div>
</template>
请检查你的发射是否仍然按预期工作。
英文:
This answer to vue 3 emit warning " Extraneous non-emits event listeners" could help you.
Wrapping the template in a <div>
fixes the warning.
<template>
<div>
<slot
...
</VDialog>
</div>
</template>
Please check if your emits still works as intended.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论