使用Vue路由器控制模态

Posted

技术标签:

【中文标题】使用Vue路由器控制模态【英文标题】:Control modals using vue router 【发布时间】:2017-05-06 02:37:00 【问题描述】:

我正在使用带有 VueRouter 的 Vue 2 开发的项目工作,我正在尝试使用由我的 VueRouter 控制的模态!

我已经完成了以下代码

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

<div id="app">
  <router-view v-if="!isLoading"></router-view>
  <router-view v-if="!isLoading" name="modal"></router-view>
</div>

RoutedModals 混合 正如您在我的 beforeRouteEnter 方法中看到的那样,我正在检查是否有以前的“来自”路由(这意味着用户在应用程序内导航页面)...如果是我将其设置为默认组件...如果没有(这意味着用户直接从 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
      
    

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


  name: 'leads.quick-add',
  path: '/leads/quick-add',
  components:  modal: QuickAdd ,
, 

  name: 'leads.index',
  path: '/leads',
  component: Main,
,

效果很好!当我访问我的模态 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
  
,

哪里有sub-router-view但是不起作用!

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

【问题讨论】:

你找到解决办法了吗? 我做了类似的事情,让路由器指向一个仅是模态的组件,并且该模态处于活动状态。然后,将模式上的关闭按钮(和或保存按钮)设置为 router.back() 分配给组件的另一个问题。默认是组件丢失了它的参数。 研究建立一个可以独立并以编程方式运行的模态系统,可能使用控制任何和所有模态的事件总线。一旦设置完成,就可以从任何地方调用模式,即在视图中(按下按钮)、通过组件状态(已安装)或可能从路由传递参数(手动 URL 条目)。这应该有助于避免与视图内容搏斗。 【参考方案1】:

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

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

首先创建一个Modal Component,通过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>

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

import Home from "./Home.vue";
import Modal from "./Modal.vue";
import Content from "./Content.vue";

const router = new VueRouter(
  routes: [
    
      path: "/",
      component: Home,
      children: [
        
          path: "create",
          component: Modal,
          props: 
            component: Content
          
        
      ]
    
  ]
);

由于modal是'/'的子路由,Home组件需要渲染router-view:

<template>
  <div>
    Hi i'am home
    <router-view />
    <router-link to="/create">open modal</router-link>
  </div>
</template>

并且 App.vue 需要渲染门户目标,因此模态框会转到内容的末尾(它使定位模态框更容易):

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

<script>
export default 
  name: "App",
;
</script>

就是这样

【讨论】:

以上是关于使用Vue路由器控制模态的主要内容,如果未能解决你的问题,请参考以下文章

带有路由器的 Vue 模态

做一个vue模态弹出框如何

结合Vue路由器使用Vue 2中的可重用组件

在 Vue 中启用(控制台)路由器事件日志记录

前端权限控制-基于vue-router的动态路由实现

vue项目路由权限控制实现(前端控制)