在Vuetify循环数据表中实现复用删除确认Dialog组件
Got it, let's get this sorted out step by step. Since you're already halfway there with your DialogBox component and delete logic, we just need to tweak a few things to make the reusable dialog work seamlessly with your datatable's delete actions.
First, let's make your DialogBox more flexible so it can accept external state, custom text, and trigger callbacks when the user confirms or cancels. We'll use Vue's v-model pattern for two-way binding of the dialog's visibility, and emit events for user actions.
Here's the updated ConfirmDialog.vue component (using Vue 3 <script setup>; adjust to Options API if you're on Vue 2):
<template> <v-dialog v-model="isVisible" width="500"> <!-- Optional activator slot if you want to use the built-in trigger --> <template v-slot:activator="{ on, attrs }" v-if="$slots.activator"> <component v-bind="attrs" v-on="on"> <slot name="activator"></slot> </component> </template> <v-card> <v-card-title class="headline grey lighten-2" primary-title> {{ title || 'Confirmation' }} </v-card-title> <v-card-text> {{ message || 'Are you sure you want to proceed?' }} </v-card-text> <v-divider></v-divider> <v-card-actions> <v-spacer></v-spacer> <v-btn color="grey" text @click="handleCancel"> Cancel </v-btn> <v-btn color="primary" text @click="handleConfirm"> Confirm </v-btn> </v-card-actions> </v-card> </v-dialog> </template> <script setup> import { computed } from 'vue'; const props = defineProps({ modelValue: { type: Boolean, default: false }, title: { type: String, default: 'Confirmation' }, message: { type: String, default: 'Are you sure?' } }); const emit = defineEmits(['update:modelValue', 'confirm', 'cancel']); // Handle v-model two-way binding const isVisible = computed({ get() { return props.modelValue; }, set(val) { emit('update:modelValue', val); } }); const handleConfirm = () => { emit('confirm'); isVisible.value = false; }; const handleCancel = () => { emit('cancel'); isVisible.value = false; }; </script>
Now let's connect this reusable dialog to your datatable. We'll use a single shared dialog (more efficient than rendering one per row) and track the item the user wants to delete.
Update your datatable component's code like this:
<template> <v-data-table ...> <template v-slot:item.action="{ item }"> <v-btn icon color="blue" :to="{ path: updatePath, query: { id: item.id } }"> <v-icon small>mdi-pencil</v-icon> </v-btn> <!-- Replace your delete button with this --> <v-btn icon color="red" @click="openDeleteDialog(item)"> <v-icon small>mdi-delete</v-icon> </v-btn> </template> </v-data-table> <!-- Add the shared confirm dialog --> <ConfirmDialog v-model="deleteDialogVisible" title="Confirm Delete" message="Are you sure you want to delete this item?" @confirm="handleDelete" /> </template> <script setup> import { ref } from 'vue'; import ConfirmDialog from './ConfirmDialog.vue'; // Adjust path to match your file structure // Track dialog visibility and the item to delete const deleteDialogVisible = ref(false); const currentDeleteItem = ref(null); // Open dialog and store the target item const openDeleteDialog = (item) => { currentDeleteItem.value = item; deleteDialogVisible.value = true; }; // Trigger your existing delete logic when confirmed const handleDelete = () => { if (currentDeleteItem.value) { $emit('deleteItem', currentDeleteItem.value); currentDeleteItem.value = null; // Reset after deletion } }; </script>
- When you click a row's delete button,
openDeleteDialogsaves the target item and opens the dialog. - The dialog displays the custom delete confirmation message.
- Clicking "Confirm" triggers the
handleDeletefunction, which emits your existingdeleteItemevent with the saved item. - Clicking "Cancel" simply closes the dialog without any action.
If you don't mind rendering one dialog per row (fine for small tables), you can skip tracking the current item and use the dialog's activator slot directly:
<template v-slot:item.action="{ item }"> <v-btn icon color="blue" :to="{ path: updatePath, query: { id: item.id } }"> <v-icon small>mdi-pencil</v-icon> </v-btn> <ConfirmDialog title="Confirm Delete" message="Are you sure you want to delete this item?" @confirm="$emit('deleteItem', item)" > <template #activator> <v-btn icon color="red"> <v-icon small>mdi-delete</v-icon> </v-btn> </template> </ConfirmDialog> </template>
This is simpler but less efficient for large datasets, since it creates a dialog component for every row.
内容的提问来源于stack exchange,提问作者Kaleem Qasim

