
Модальные диалоги не такая и сложная задача в разработке. Разве что можно легко запутаться в коде, если нужно вызывать модальные окна по цепочке. Но это очень монотонная и неинтересная работа с повторяющейся логикой, которую подчас копируют из компонента в компонет с незначительными изменениями.
Хорошим решением было бы создать функцию, которая принимала бы компонент диалога и управляла бы его рендерингом в шаблоне, а этот диалог можно "промисифицировать" и работать с ним как с асинхронной функцией. Как например в этой библиотеке vue-modal-dialogs. К сожалению она давно не обновлялась и не опддерживает Vue 3.
А еще отличной идеей для организации кода было бы отдельные хуки, код в которых выполнялся бы в зависимости от действий пользователя.
Все это есть в плагине vuejs-confirm-dialog о котором я хочу вам рассказать.
Конечный результат можно посмотреть в песочнице. Код немного отличается от того. что в посте.
Установка
Начнем с создания нового проекта на Vue 3. Введем в консоли:
vue create dialogs-guide
// Pick a second option
? Please pick a preset:
Default ([Vue 2] babel, eslint)
> Default (Vue 3) ([Vue 3] babel, eslint)
Manually select featuresМы получили стандартный шаблон нового проекта. Далее установим библиотеку согласно документации в README.md.
npm i vuejs-confirm-dialogЗаменим код в main.js на такой:
import { createApp } from 'vue'
import App from './App.vue'
import * as ConfirmDialog from 'vuejs-confirm-dialog'
createApp(App).use(ConfirmDialog).mount('#app')Использование
Теперь перейдем в файл App.vue. Первым делом исправим код шаблона. Для работы библиотеки нам обязательно нужно добавить в него компонент <DialogsWrapper /> и удалим HelloWord:
<template>
<img alt="Vue logo" src="./assets/logo.png">
<DialogsWrapper />
</template>Теперь изучим как использовать функцию createConfirmDialog. Используем новый синтаксис setup для раздела script. createConfirmDialog первым аргументом принимает компонент, который будет использоваться как модальное окно, а вторым входные данные для него. Функция возвращает обьект с методами для работы с модальным окном, так метод reveal вызывает диалог, а хук onConfirm принимает код, который выполниться если пользователь нажмет на "согласен". Можно заставить появляться компонерт HelloWord при нажатии на лого и передать ему значение пропса msg:
// App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" @click="reveal">
<DialogsWrapper />
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import { createConfirmDialog } from 'vuejs-confirm-dialog'
const { reveal } = createConfirmDialog(HelloWorld, { msg: 'Hi!'})
</script>Никакой дополнительной логики не требуется. Компонент отрисовывается после вызова функции reveal и исчезает после того, как пользователь отреагирует на диалог.
Реальный пример компонента
Теперь напишем что-то более приближенное к реальному использованию.
Создадим новый компонент SimpleDialog.vue в папке components:
<template>
<div class="modal-container">
<div class="modal-body">
<span class="modal-close" @click="emit('cancel')"> 