Управление модальными окнами

В библиотеке Element Plus модальные окна представлены компонентом ElDialog. Этот компонент позволяет создавать как простые диалоговые окна, так и сложные модальные интерфейсы с формами, подтверждениями и динамическим содержимым. Основной принцип работы заключается в управлении видимостью диалога через реактивное состояние.

Простейший пример:

<template>
  <el-button @click="dialogVisible = true">Открыть окно</el-button>
  
  <el-dialog
    title="Пример диалога"
    :visible.sync="dialogVisible"
    width="50%">
    <span>Содержимое модального окна</span>
    <template #footer>
      <el-button @click="dialogVisible = false">Закрыть</el-button>
      <el-button type="primary" @click="confirm">Подтвердить</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref } from 'vue';

const dialogVisible = ref(false);

function confirm() {
  console.log('Действие подтверждено');
  dialogVisible.value = false;
}
</script>

Ключевые моменты:

  • Атрибут :visible.sync обеспечивает двустороннюю привязку состояния видимости окна.
  • title задаёт заголовок диалога.
  • Слот footer позволяет кастомизировать нижнюю панель с кнопками.

Настройка размеров и позиционирования

Диалоговые окна в Element Plus имеют гибкие настройки размеров и позиционирования:

  • width — ширина окна (px или %).
  • top — отступ от верхнего края страницы, по умолчанию 15px.
  • fullscreen — булевое свойство, превращающее окно в полноэкранное.
  • center — выравнивание содержимого по центру.

Пример использования:

<el-dialog
  title="Центрированный диалог"
  :visible.sync="dialogVisible"
  width="600px"
  top="100px"
  :center="true">
  <p>Контент по центру окна</p>
</el-dialog>

Управление событиями

Компонент ElDialog предоставляет несколько событий для контроля жизненного цикла модального окна:

  • open — срабатывает при открытии диалога.
  • opened — после полной анимации открытия.
  • close — при попытке закрытия (можно предотвратить закрытие через before-close).
  • closed — после завершения анимации закрытия.

Пример с before-close:

<el-dialog
  title="Подтверждение закрытия"
  :visible.sync="dialogVisible"
  :before-close="handleClose">
  <p>Попытка закрытия будет проверена</p>
</el-dialog>

<script setup>
function handleClose(done) {
  if (confirm('Вы действительно хотите закрыть окно?')) {
    done();
  }
}
</script>

done — это callback, который необходимо вызвать для фактического закрытия диалога. Такой подход позволяет добавлять проверки и предупреждения.


Модальные окна с динамическим содержимым

Часто требуется показывать диалог с данными, которые загружаются динамически. Для этого используют реактивные переменные и асинхронные функции.

Пример:

<template>
  <el-button @click="openDialog(1)">Показать данные пользователя</el-button>

  <el-dialog :visible.sync="dialogVisible" title="Информация о пользователе">
    <div v-if="loading">Загрузка...</div>
    <div v-else>
      <p>Имя: {{ userData.name }}</p>
      <p>Email: {{ userData.email }}</p>
    </div>
  </el-dialog>
</template>

<script setup>
import { ref } from 'vue';

const dialogVisible = ref(false);
const userData = ref({});
const loading = ref(false);

async function openDialog(userId) {
  dialogVisible.value = true;
  loading.value = true;
  // имитация запроса
  const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
  userData.value = await response.json();
  loading.value = false;
}
</script>

Здесь важно:

  • Использовать отдельные реактивные переменные для состояния загрузки.
  • Не блокировать открытие окна до получения данных, чтобы пользователь видел индикатор загрузки.

Анимация и кастомизация

Element Plus поддерживает встроенные анимации открытия и закрытия, основанные на переходах Vue. Для расширенной кастомизации можно использовать transition и CSS-переменные:

.el-dialog__header {
  background-color: #409eff;
  color: white;
}

.el-dialog__body {
  font-size: 16px;
  line-height: 1.5;
}

Также можно использовать destroy-on-close для очистки содержимого при закрытии:

<el-dialog :visible.sync="dialogVisible" destroy-on-close>
  <my-component />
</el-dialog>

Это особенно важно для форм, чтобы состояние не сохранялось между открытием и закрытием.


Управление модальными стэками

Когда на странице одновременно открыто несколько диалогов, важно управлять порядком слоёв (z-index). Element Plus автоматически увеличивает z-index для новых диалогов, но при необходимости можно вручную задать modal-append-to-body и custom-class:

<el-dialog
  :visible.sync="dialogVisible"
  modal-append-to-body
  custom-class="custom-dialog">
  <p>Особый стиль модального окна</p>
</el-dialog>

<style>
.custom-dialog {
  border-radius: 12px;
  overflow: hidden;
}
</style>

Интеграция с формами

Модальные окна часто содержат формы. Element Plus позволяет интегрировать ElForm с полной валидацией и управлением отправкой данных:

<el-dialog :visible.sync="dialogVisible" title="Форма пользователя">
  <el-form :model="formData" ref="formRef" label-width="120px">
    <el-form-item label="Имя" prop="name" :rules="[{ required: true, message: 'Введите имя', trigger: 'blur' }]">
      <el-input v-model="formData.name" />
    </el-form-item>
    <el-form-item label="Email" prop="email" :rules="[{ type: 'email', message: 'Некорректный email', trigger: 'blur' }]">
      <el-input v-model="formData.email" />
    </el-form-item>
  </el-form>
  <template #footer>
    <el-button @click="dialogVisible = false">Отмена</el-button>
    <el-button type="primary" @click="submitForm">Сохранить</el-button>
  </template>
</el-dialog>

<script setup>
import { ref } from 'vue';

const dialogVisible = ref(false);
const formData = ref({ name: '', email: '' });
const formRef = ref(null);

function submitForm() {
  formRef.value.validate(valid => {
    if (valid) {
      console.log('Данные формы:', formData.value);
      dialogVisible.value = false;
    }
  });
}
</script>

Использование ref и метода validate позволяет полностью контролировать отправку формы и предотвращать закрытие диалога при ошибках.


Особенности UX

  • Рекомендовано использовать модальные окна для критических действий или ввода данных, а не для простых уведомлений.
  • Для простых уведомлений лучше применять ElMessage или ElNotification.
  • Важно предусматривать пользовательский контроль закрытия через esc и клик по затемнённой области (close-on-click-modal), особенно если диалог содержит несохранённые данные.

Эта структура и набор практик обеспечивают полноценное управление модальными окнами в Element Plus, позволяя создавать интерфейсы с высокой интерактивностью, безопасностью и удобством для пользователя.