使用vue路由器控制模态

Gus*_*lli 10 javascript modal-dialog vue-router vuejs2

我正在使用Vue 2和VueRouter开发的项目,我正在尝试使用我的VueRouter控制的模态!

我已经完成了以下代码

主要vue组件:我的普通组件将被加载到默认的路由器视图中,我的所有模态将被加载到模态路由器视图中

<div id="app">
  <router-view v-if="!isLoading"></router-view>
  <router-view v-if="!isLoading" name="modal"></router-view>
</div>
Run Code Online (Sandbox Code Playgroud)

RoutedModals混音正如您在我的beforeRouteEnter方法中看到的那样,我正在检查是否存在之前的"from"路线(这意味着用户在应用程序内部导航页面)...如果是,我将其设置为默认组件...如果不是(这意味着用户直接从URL获得)我将我的仪表板设置为默认值,它将在我的模态后面打开.

import Dashboard from 'modules/dashboard/components/Main.vue'
import { isNil } from 'lodash'

export default {
  data() {
      return {
        canAccessDirect: true,
        goBackTo: '/'
      }
    },
    beforeRouteEnter(to, from, next) {
      to.matched[0].components.default = isNil(from.matched[0]) ? Dashboard : from.matched[0].components.default

      next(vm => {
        if (!vm.canAccessDirect)
          vm.$router.push({
            name: 'dashboard.index'
          })

        vm.fetchRecords()
        vm.goBackTo = from.path
        window.jQuery(vm.$el).modal('show')
        window.jQuery(vm.$el).on('hide.bs.modal', () => {
          vm.$router.push(vm.goBackTo)
        })
      })
    },
    beforeRouteLeave(to, from, next) {
      setTimeout(() => {
        next()
      }, 200)
    },
    methods: {
      fetchRecords() {
        // Do list request
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的路由器对象的一个​​示例:第一个路由将在路由器视图模式上打开一个模态,第二个路由将仅在默认路由器视图上打开

{
  name: 'leads.quick-add',
  path: '/leads/quick-add',
  components: { modal: QuickAdd },
}, 
{
  name: 'leads.index',
  path: '/leads',
  component: Main,
},
Run Code Online (Sandbox Code Playgroud)

它很棒!当我访问我的模态URL(无论是直接或导航)并且默认组件具有子组件时,问题就出现了!儿童组件逃脱了这种情况!

附上一些截图可以帮助您了解发生的情况......

图片1 在此输入图像描述

图2 在此输入图像描述

在图1中,我们可以使用2个组件,其中数字1是我的VueRouter上的默认组件,数字2是他的孩子!

Ar图像2,点击+报价按钮后加载模态,组件编号为2!

关于如何保留其他组件的任何想法?

只是为了清楚我想通过路由来做,而不是手动调用我的模态!

##########################编辑 我正在尝试做类似的事情而不是检查beforeRouterEnter方法:

{
  name: 'leads.show.quotations.create',
  path: '/leads/:id/quotations/create',
  components: {
    default: Show,
    'default.tab': Quotations,
    modal: Add
  },
  meta: {
    requiresAuth: true
  }
},
Run Code Online (Sandbox Code Playgroud)

哪里有子路由器视图但它不起作用!

考虑可能性我在github repo上添加了这个问题:https: //github.com/vuejs/vue-router/issues/1030

小智 7

我在工作的一个项目中做到了这一点。实际上很简单,困难的部分在于混合你那里的 jquery,也许还有 css 来定位模态,因为它的入口点是组件内的路由器视图,我建议使用包Portal-vue来移动模态内容到正文的末尾。

这是一个工作示例:https ://codesandbox.io/s/vue-router-modal-j10t2

首先创建一个模态组件,通过 props 接收它的子组件:

<template>
  <portal to="modal">
    <div class="modal-wrapper">
      <div class="overlay" @click="$router.back()"></div>
      <div class="modal">
        <!-- you can use v-bind to pass down all props -->
        <component :is="component" v-bind="$attrs"/>
      </div>
    </div>
  </portal>
</template>

<script>
export default {
  name: "Modal",
  props: ["component"],
};
</script>

<style scoped>
.modal-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}
.modal {
  position: absolute;
  z-index: 1;
  margin: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 5em;
  border: 1px solid #ccc;
  border-radius: 1em;
  box-shadow: 0 0 1em #00000033;
}

.overlay {
  z-index: 1;
  position: absolute;
  width: 100vw;
  height: 100vh;
  background-color: #00000055;
}
</style>

Run Code Online (Sandbox Code Playgroud)

然后,您可以使用路由中的 props 为给定路由分配内容:

<template>
  <portal to="modal">
    <div class="modal-wrapper">
      <div class="overlay" @click="$router.back()"></div>
      <div class="modal">
        <!-- you can use v-bind to pass down all props -->
        <component :is="component" v-bind="$attrs"/>
      </div>
    </div>
  </portal>
</template>

<script>
export default {
  name: "Modal",
  props: ["component"],
};
</script>

<style scoped>
.modal-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}
.modal {
  position: absolute;
  z-index: 1;
  margin: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 5em;
  border: 1px solid #ccc;
  border-radius: 1em;
  box-shadow: 0 0 1em #00000033;
}

.overlay {
  z-index: 1;
  position: absolute;
  width: 100vw;
  height: 100vh;
  background-color: #00000055;
}
</style>

Run Code Online (Sandbox Code Playgroud)

由于模态框是“/”的子路由,因此 Home 组件需要渲染路由器视图:

<template>
  <div>
    Hi i'am home
    <router-view />
    <router-link to="/create">open modal</router-link>
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

App.vue 需要渲染门户目标,因此模式会转到内容的末尾(这使得定位模式变得更加容易):

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" width="25%" />
    <router-view />
    <portal-target name="modal" />
  </div>
</template>

<script>
export default {
  name: "App",
};
</script>
Run Code Online (Sandbox Code Playgroud)

就是这样