Как организовать роутинг для модального окна в Vue.js?

Имеется текущая реализация модальных окон с использованием библиотеки vue-final-modal. Мне необходимо создать динамические модальные окна с маршрутизацией, например, по шаблону <code>/product/:id</code>. Хотя существует библиотека genesis-vue-modal с готовым роутингом, переход на нее ради возможности маршрутизации кажется нецелесообразным, как и разработка собственного решения для модальных окон. Есть ли у кого-нибудь готовая реализация динамических модальных окон на основе vue-final-modal?
  • 24 января 2025 г. 1:54
Ответы на вопрос 2
Конечно! Организовать роутинг для модальных окон в Vue.js с использованием `vue-final-modal` можно вполне просто. Ниже приведен пример, который демонстрирует, как это можно сделать.

### Шаги для реализации динамических модальных окон

1. **Установить vue-final-modal:**
   Убедитесь, что у вас установлен `vue-final-modal`. Если нет, вы можете установить его с помощью npm или yarn:
   ```bash
   npm install vue-final-modal
   ```
   или
   ```bash
   yarn add vue-final-modal
   ```

2. **Создайте маршруты:**
   Настройте ваши маршруты в `vue-router`, чтобы включить динамические маршруты для модальных окон.

   ```javascript
   import Vue from 'vue';
   import Router from 'vue-router';
   import Product from './views/Product.vue'; // шаблон для продукта

   Vue.use(Router);

   export default new Router({
     routes: [
       {
         path: '/product/:id',
         component: Product,
         props: true,
         meta: { modal: true } // Добавьте мета-информацию для роутинга модала
       }
     ]
   });
   ```

3. **Создайте базовый модальный компонент:**
   Сделайте компонент, который будет представлять модальное окно.

   ```vue
   <template>
     <vfm-modal v-model="isModalVisible">
       <component :is="activeComponent" :id="productId"></component>
     </vfm-modal>
   </template>

   <script>
   import { Vfm } from 'vue-final-modal';
   import ProductDetails from './ProductDetails.vue'; // Компонент для отображения деталей продукта

   export default {
     components: { Vfm, ProductDetails },
     computed: {
       isModalVisible() {
         return this.$route.meta.modal; // Отображать ли модальное окно
       },
       productId() {
         return this.$route.params.id; // Получаем ID продукта из параметров маршрута
       },
       activeComponent() {
         return this.$route.meta.modal ? 'ProductDetails' : null;
       }
     },
     watch: {
       $route(to, from) {
         // Убедитесь, что модальное окно закрыто при изменении маршрута, если оно не имеет модального пути
         if (!to.meta.modal) {
           this.isModalVisible = false;
         }
       }
     }
   };
   </script>
   ```

4. **Используйте модальные окна в вашем приложении:**
   Убедитесь, что ваш основной компонент (например, `App.vue`) содержит ваш роутер и комбинует маршрутизацию с модальными окнами.

   ```vue
   <template>
     <div id="app">
       <router-view></router-view>
     </div>
   </template>

   <script>
   export default {
     // Вы можете добавить дополнительные настройки или методы, если это необходимо
   };
   </script>
   ```

### Нюансы:

- Убедитесь, что ваш роутер поддерживает історическую навигацию и правильно настроен для обработки URL-адресов с параметрами.
- Возможно, потребуется настроить `router.beforeEach`, чтобы управлять состоянием модального окна в зависимости от маршрута.
- Проверьте, нужно ли вам добавить дополнительные стили или логику для лучшего UX, когда открывается модальное окно.

Такой подход позволяет вам динамически открывать модальные окна, основываясь на текущем маршруте, не теряя при этом преимущества от использования `vue-final-modal`.
Если product действительная страница и при "переходе" с /product/ на /product/:id нужно сделать открытие модального окна, то можно сделать это через отслеживания роутера. 

const dialog = ref(false)
watch(
 () => route.params?.id
 (newId, oldId) => {
  if (newId === oldId) return
  dialog.value = true
 }
)

const openProduct = (id) => {
 router.push({ name: 'Product', params: { id } }).catch(() => {})
}
Похожие вопросы