Во vue я видел множество реализаций диалоговых окон и все они были слишком громоздкими и неудобными. И вот, в новом, начатом мной проекте я решил исправить данные проблемы.
Концепция
Вся система будет работать довольно просто, для отображения нужного нам диалогового окна надо будет всего лишь изменить один query параметр в адресной строке браузера, для примера назовем этот параметр ‘dialog’. Соответственно для закрытия окна надо будет только убрать параметр dialog.
Само окно будет состоять из четырех блоков:
‘Dialog-control-panel’ в нем будут располагаться кнопки управления
“Dialog-content” в этой области будут динамически появляться vue компоненты с нужным нам контентом
“Dialog-left-btn” и “Dialog-right-btn” кнопки которые можно вызывать по мере надобности, нужны для переключения контента

Начало работы
Создадим нужные нам компоненты:
“TheDialog.vue” - главный компонент в котором будет все происходить
“DialogAbout.vue” и “DialogContacts.vue” - компоненты с контентом для нашего диалогового окна

Необходимое в vuex
В папке проекта “store” создадим еще одну директорию “dialog”, в ней уже на понадобятся 3 файла “state.js”, “mutations.js” и “index.js”.
Как уже стало понятно, файл “state.js” нужен нам для хранения состояний диалогового окна, в нем я пропишу несколько объектов с полями active и to.
Если в active стоит значение “true”, то данный элемент будет отображаться в диалоговом окне.
Свойство to должно хранить в себе ссылку или же пустую строку.
export default function () { return { leftBtn: { active: false, to: "", }, rightBtn: { active: false, to: "", }, downloadBtn: { active: false, to: "", }, backBtn: { active: false, to: "", }, }; }
Файл “mutations.js” содержит в себе мутации для изменения состояний нашего диалогового окна.
export function changeStatusLeftBtn(state, active = false, to = "") { state.leftBtn = { active, to }; } export function changeStatusRightBtn(state, active = false, to = "") { state.rightBtn = { active, to }; } export function changeStatusDownloadBtn(state, active = false, to = "") { state.downloadBtn = { active, to }; } export function changeStatusBackBtn(state, active = false, to = "") { state.backBtn = { active, to }; }
“index.js” нам нужен для соединения всех файлов в один модуль
import state from './state' import * as mutations from './mutations' export default { state, mutations, }
После данных манипуляций мы можем добавить модуль dialog в store.
import dialog from "./dialog"; const Store = createStore({ modules: { dialog, }, });
Наконец мы подошли к главному компоненту “TheDialog.vue”
Разметка
Здесь мы размечаем само диалоговое окно, четыре главных блока, кнопки которые будут отображаться в зависимости от состояния, а так же указываем место, где будут динамически меняться компоненты.
<template> <div class="dialog-bg"> <div class="dialog-control-panel"> <div class="panel"> <div class="btn" v-ripple v-if="backBtn.active"> <q-icon name="eva-arrow-back-outline" /> </div> </div> <div class="panel"> <div class="btn" v-ripple v-if="downloadBtn.active"> <q-icon name="eva-cloud-download-outline" /> </div> <div class="btn" v-ripple> <q-icon name="eva-close-outline" /> </div> </div> </div> <div class="btn right" v-ripple v-if="rightBtn.active"> <q-icon name="eva-arrow-ios-forward-outline" /> </div> <div class="btn left" v-ripple v-if="leftBtn.active"> <q-icon name="eva-arrow-ios-back-outline" /> </div> <div class="dialog-content"> <component :is="requiredModule" /> </div> </div> </template>
Логика
<script> import DialogAbout from "components/dialog/DialogAbout"; import DialogContacts from "components/dialog/DialogContacts"; import { defineComponent, computed } from "vue"; import { useRoute } from "vue-router"; import { useStore } from "vuex"; export default defineComponent({ name: "TheDialog", setup() { const $store = useStore(); const $route = useRoute(); const requiredModule = computed(() => { const dialog = $route.query.dialog; if (dialog === "about") return DialogAbout; if (dialog === "contacts") return DialogContacts; return false; }); const backBtn = $store.state.dialog.backBtn; const downloadBtn = $store.state.dialog.downloadBtn; const leftBtn = $store.state.dialog.leftBtn; const rightBtn = $store.state.dialog.rightBtn; return { requiredModule, backBtn, downloadBtn, leftBtn, rightBtn, }; }, }); </script>
Здесь нет ничего сложного, просто из функции setup мы возвращаем нужные нам состояния для отображения кнопок и результат computed функции.
Добавим немного стилей
<style lang="scss" scoped> .dialog-bg { width: 100%; min-height: 100vh; background-color: rgba(30, 30, 30, 0.9); position: fixed; left: 0; top: 0; z-index: 10; padding: 100px 0; .btn { width: 80px; height: 80px; color: rgba(255, 255, 255, 0.637); font-size: 1.8rem; display: flex; justify-content: center; align-items: center; cursor: pointer; position: relative; transition: background-color 0.2s; &:hover { background-color: rgba(0, 0, 0, 0.2); } } .dialog-control-panel { width: 100%; display: flex; justify-content: space-between; position: fixed; top: 0; left: 0; .panel { display: flex; } } .right, .left { position: fixed; height: calc(100vh - 160px); top: 80px; } .right { right: 0; } .left { left: 0; } .dialog-content { max-width: 732px; margin: auto; } } </style>
Результат
Все! Наше диалоговое окно готово.


