VueJs + VueRouter + modal. Очередной велосипед

    Добрый день. В этой статье я разберу способ, который позволяет при смене адреса показывать модальное окно для наших нужд. Я знаю, что есть собственное решение для компонента «modal» на официальном сайте. Вдобавок к этому на Хабре есть много других статей, посвященных теме модальных окон во VueJs (например, вот эта).

    Однако, на мой взгляд, каждый из них имеет свои минусы, например:

    • в случае изложенном на офф сайте компоненты нужно создавать отдельную переменную и привязываться к ней;
    • во второй статье рассматриваются решения сторонних разработчиков. В этом случае нужно потратить время и разобраться как использовать эти компоненты + лишние, на мой взгляд, зависимости в проект. А я придерживаюсь позиции: чем проще, тем лучше.

    Опять же, я всего знать не могу, поэтому, если если у вас есть что сказать или отметить, то я открыт к конструктивной критике. Далее мы будем использовать исключительно стандартный функционал инструментов, которые используем (Vue, VueRouter, Bootstrap Modal). Итак, ближе к делу…

    Найдутся люди, которые скажут: «лучше подключить npm-зависимости для modal, чем тянуть весь bootstrap + jquery.». Товарищи, вам никто не мешает все это дело адаптировать под ваши нужды и инструменты. Приведенные инструменты лишь пример реализации.

    Сразу рабочий вариант.

    HTML
    <div id="app">
      <nav>
        <router-link :to="{ name: 'modal' }" exact>Open Modal</router-link>
      </nav>
      
      <router-view></router-view>
    </div>
    


    javascript
    Vue.use(VueRouter)
    
    const Modal = {
    	template: `<div class="modal fade" tabindex="-1" role="dialog" ref="modal">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Modal title</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">×</span>
            </button>
          </div>
          <div class="modal-body">
            <p>Modal body text goes here.</p>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
          </div>
        </div>
      </div>
    </div>
    mounted: function(){
    	console.log('mounted')
    
    	var context = this;
    
    	$(this.$refs.modal).modal('show')
      
      $(this.$refs.modal).on('hidden.bs.modal', function(){
      	context.$router.go(-1);
      })
    }
    }
    
    
    const routes = [
      { path: '/modal', name: 'modal', component: Modal },
    ]
    
    const router = new VueRouter({
    	routes,
    })
    
    // New VueJS instance
    var app = new Vue({
    	// CSS selector of the root DOM element
      el: '#app',
      // Inject the router into the app
      router,
    })
    


    Собственно, здесь нет ничего сложного.

    1. При переходе по нашей ссылке, монтируется наш компонент Modal.
    2. При его монтировании мы открываем наше модальное окно и через this.$refs отслеживаем его закрытие.
    3. При его закрытии мы программно возвращаем человека на шаг назад, чтобы наш компонент отмонтировался.

    Таким образом, такой подход и такая структура неплохое решение, если у вас в проекте планируется много модальных окон со своей отдельной логикой:

    • легкая кастомизация;
    • не нужно подгружать сторонние зависимости. Лично для меня чем проще, тем лучше;

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 10

      +1

      Рендерить jQuery с помощью Vue?)

        +1

        Я правильно понял, что вы не захотели подключать сторонние библиотеки, но подключили бутстрап и jquery, чтобы написать свой код?

          +1
          Знатное извращение… если надо логику степ бай степ… то зачем нужно модальное окно вообще?… можно просто отслеживать историю хождений и тп
            +2
            — var в 2019 году
            — jquery + $refs
            — модалка заменит содержимое текущей страницы в router-view, а не просто отрендерится поверх
            — переиспользовать невозможно, где хотя бы слоты для контента?
            — перезагрузка страницы на урле модалки при закрытии куда юзера кинет?

              –4
              • var в 2019 году — да, представляете какой я старый?!) На самом деле Вы действительно считаете это критичным?;
              • jquery + $refs — в статье отмечено, что это лишь пример реализации. В ваших проектах, наверняка, используются другие kit-ы;
              • модалка заменит содержимое текущей страницы в router-view, а не просто отрендерится поверх — Вы пример-то смотрели?;
              • переиспользовать невозможно, где хотя бы слоты для контента — в моей задумке ( каждое отдельное окно — это отдельный уникальный компонент со своей логикой, кодом и структурой. Мне видится, что «переиспользовать» здесь ни к месту;
              • перезагрузка страницы на урле модалки при закрытии куда юзера кинет? — Вы пример смотрели?


              Считаю, объективней было бы с вашей стороны сделать свою улучшенную реализацию и поделиться ею в комментах.
                0
                По пункту 3. Я правильно понимаю, Вы предлагаете писать отдельный роут для каждого модального окна и добавлять на каждую страницу где используется модальное окно <router-view>? Без <router-view> всегда будет происходить перересовка основного контента страницы jsfiddle.net/leos0331/4L8wvh3y.
                0
                Если я правильно понял задачу, то делал что-то подобное на днях. Пример. Компонент окна брал из element-ui. В вашей реализации смущает использование $router.go(-1). Получается, если открыть модальное окно по прямой ссылке, то при его закрытии не поменяется url.
                  0
                  Вы не по назначению используйте router-link. Оно, конечно, у вас работать будет, но другие разработчики после вас увидев в коде router-link сразу не догадаются, что это просто кнопка для раскрытия модалки. router-link всё-таки это про переходы на другие страницы сайта. Для раскрытия модалки (с точки зрения семантики) лучше применять button.
                    +2

                    В чём проблема с тем чтобы привязать модальное окно к модулю Vuex и использовать middleware роутера?
                    Вешать логику роутера на модальное окно — это грубое наршение SRP. Появилась ненужная связь модального окна и роутера, такой код будет невозможно поддерживать.
                    Использование Vuex избавит вас от глобальных переменных и позволит более гибко контролировать поведение модального окна.
                    Вам правильно подсказали что такой подход будет перезагружать страницу. У вас на начальной странице ничего нет. Попробуйте добавить туда что-нибудь и увидите как при каждом закрытии окна весь контент рендрится заново. (пример: https://jsfiddle.net/uyqmL7ro/)

                      0

                      Возвращать на шаг назад в истории — так себе решение. А если я по внешней ссылке перешёл?

                      Only users with full accounts can post comments. Log in, please.