В библиотеке Element Plus диалоги реализуются с
помощью компонента <el-dialog>, который предоставляет
богатый функционал для создания модальных окон. Часто возникает
необходимость организовать вложенные диалоги, когда
один диалог открывает другой. В таких случаях важно правильно управлять
состояниями и событиями, чтобы избежать конфликтов и обеспечить
корректное поведение интерфейса.
Для начала рассмотрим структуру простого диалога:
<template>
<el-dialog
title="Основной диалог"
:visible.sync="mainDialogVisible"
width="50%">
<p>Содержимое основного диалога</p>
<span slot="footer" class="dialog-footer">
<el-button @click="mainDialogVisible = false">Закрыть</el-button>
<el-button type="primary" @click="nestedDialogVisible = true">Открыть вложенный</el-button>
</span>
</el-dialog>
<el-dialog
title="Вложенный диалог"
:visible.sync="nestedDialogVisible"
width="30%">
<p>Содержимое вложенного диалога</p>
<span slot="footer" class="dialog-footer">
<el-button @click="nestedDialogVisible = false">Закрыть</el-button>
</span>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
const mainDialogVisible = ref(false)
const nestedDialogVisible = ref(false)
</script>
Ключевые моменты:
:visible.sync, чтобы диалог автоматически
реагировал на изменения состояния переменной.ref).При использовании нескольких диалогов важно учитывать:
autofocus.<el-dialog
title="Вложенный диалог"
:visible.sync="nestedDialogVisible"
:modal-append-to-body="false">
</el-dialog>
modal-append-to-body="false" позволяет
вложенному диалогу находиться внутри родительского контейнера, что
удобно для сложных макетов и анимаций.Часто требуется, чтобы вложенный диалог передавал данные обратно в родительский. Используются реактивные объекты:
<script setup>
import { reactive } from 'vue'
const formData = reactive({
name: '',
age: null
})
const mainDialogVisible = ref(false)
const nestedDialogVisible = ref(false)
function saveNestedData(data) {
formData.name = data.name
formData.age = data.age
nestedDialogVisible.value = false
}
</script>
<template>
<el-dialog
title="Основной диалог"
:visible.sync="mainDialogVisible">
<p>Имя: {{ formData.name }}, Возраст: {{ formData.age }}</p>
<el-button @click="nestedDialogVisible = true">Редактировать</el-button>
</el-dialog>
<el-dialog
title="Вложенный диалог"
:visible.sync="nestedDialogVisible">
<el-input v-model="formData.name" placeholder="Введите имя"></el-input>
<el-input-number v-model="formData.age" placeholder="Введите возраст"></el-input-number>
<el-button type="primary" @click="saveNestedData(formData)">Сохранить</el-button>
</el-dialog>
</template>
formData обеспечивает
синхронизацию данных между диалогами без лишних событий.saveNestedData закрывает вложенный диалог после
сохранения.Element Plus предоставляет события:
open – срабатывает при открытии диалога.opened – после завершения анимации открытия.close – перед закрытием диалога.closed – после завершения анимации закрытия.Пример управления закрытием:
<el-dialog
title="Основной диалог"
:visible.sync="mainDialogVisible"
@close="handleMainClose">
</el-dialog>
<script setup>
function handleMainClose() {
if (nestedDialogVisible.value) {
nestedDialogVisible.value = false
}
}
</script>
Для сложных интерфейсов часто используются формы внутри диалогов:
<el-dialog
title="Форма в основном диалоге"
:visible.sync="mainDialogVisible">
<el-form :model="formData" ref="mainForm">
<el-form-item label="Имя" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="Возраст" prop="age">
<el-input-number v-model="formData.age"></el-input-number>
</el-form-item>
</el-form>
<el-button @click="nestedDialogVisible = true">Открыть вложенный</el-button>
</el-dialog>
<el-dialog
title="Редактирование имени"
:visible.sync="nestedDialogVisible">
<el-form :model="formData" ref="nestedForm">
<el-form-item label="Имя" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
</el-form>
<el-button type="primary" @click="nestedForm.validate(valid => valid && nestedDialogVisible = false)">Сохранить</el-button>
</el-dialog>
ref для валидации.v-if вместо v-show.<Suspense> или динамический
import().width,
top, custom-class.<el-dialog
title="Вложенный диалог"
:visible.sync="nestedDialogVisible"
custom-class="nested-dialog">
</el-dialog>
<style>
.nested-dialog .el-dialog__header {
background-color: #f5f7fa;
}
.nested-dialog .el-dialog__body {
font-size: 14px;
}
</style>
Эта структура и подходы позволяют создавать глубокие, управляемые и реактивные вложенные диалоги в Element Plus, обеспечивая удобство работы с данными, событиями и визуальными эффектами.