Единая система диалоговых окон на vue-cli при помощи vuex и vue-router

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Во vue я видел множество реализаций диалоговых окон и все они были слишком громоздкими и неудобными. И вот, в новом, начатом мной проекте я решил исправить данные проблемы.

Концепция

Вся система будет работать довольно просто, для отображения нужного нам диалогового окна надо будет всего лишь изменить один query параметр в адресной строке браузера, для примера назовем этот параметр ‘dialog’. Соответственно для закрытия окна надо будет только убрать параметр dialog.

Само окно будет состоять из четырех блоков:

  1. ‘Dialog-control-panel’ в нем будут располагаться кнопки управления

  2. “Dialog-content” в этой области будут динамически появляться vue компоненты с нужным нам контентом

  3. “Dialog-left-btn” и “Dialog-right-btn” кнопки которые можно вызывать по мере надобности, нужны для переключения контента

Начало работы

Создадим нужные нам компоненты:

  1. “TheDialog.vue” - главный компонент в котором будет все происходить

  2. “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: "",
    },
  };
}

Файл “mustations.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>

Результат

Все! Наше диалоговое окно готово.

Источник: https://habr.com/ru/post/593407/


Интересные статьи

Интересные статьи

Всем привет! В процессе работы над гексаподом AIWM я все чаще задумывался о каком-нибудь удобном интерфейсе для общения с ним. В результате тесной работы с Linux через терминал я подумал, а почему бы ...
Предыстория Когда-то у меня возникла необходимость проверять наличие неотправленных сообщений в «1С-Битрикс: Управление сайтом» (далее Битрикс) и получать уведомления об этом. Пробле...
В 1С-Битрикс: Управление сайтом (как и в Битрикс24) десятки, если не сотни настраиваемых типов данных (или сущностей): инфоблоки, пользователи, заказы, склады, форумы, блоги и т.д. Стр...
Некоторое время назад мне довелось пройти больше десятка собеседований на позицию php-программиста (битрикс). К удивлению, требования в различных организациях отличаются совсем незначительно и...
С версии 12.0 в Bitrix Framework доступно создание резервных копий в автоматическом режиме. Задание параметров автоматического резервного копирования производится в Административной части на странице ...