我正在使用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>
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
}
}
}
我的路由器对象的一个示例:第一个路由将在路由器视图模式上打开一个模态,第二个路由将仅在默认路由器视图上打开
{
name: 'leads.quick-add',
path: '/leads/quick-add',
components: { modal: QuickAdd },
},
{
name: 'leads.index',
path: '/leads',
component: Main,
},
效果很好!当我访问我的模态URL(无论是直接或导航)并且默认组件具有子组件时,问题就出现了!儿童组件逃脱了这种情况!
附上一些截图可帮助您了解会发生什么......
在图1中,我们可以使用2个组件,其中数字1是我的VueRouter上的默认组件,而数字2是他的孩子!
在图像2中,点击+报价按钮后,加载了模态,组件编号为2逃生!
关于如何保留其他组件的任何想法?
为了清楚我想通过路由来做,而不是手动调用我的模态!
##########################编辑 我正在尝试做类似的事情而不是检查之前的路由器方法:
{
name: 'leads.show.quotations.create',
path: '/leads/:id/quotations/create',
components: {
default: Show,
'default.tab': Quotations,
modal: Add
},
meta: {
requiresAuth: true
}
},
哪里有子路由器视图但它不起作用!
考虑可能性我在github repo上添加了这个问题: https://github.com/vuejs/vue-router/issues/1030
答案 0 :(得分:0)
我在工作中的一个项目中做到了这一点。实际上很简单,困难的部分在于混合您在那里拥有的 jquery,也许还有用于定位模态的 css,因为它的入口点是组件内的路由器视图,我建议使用包 portal-vue将模态内容移动到正文的末尾。
这是一个工作示例:https://codesandbox.io/s/vue-router-modal-j10t2
首先创建一个 Modal 组件,通过 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>
然后你可以使用路由中的 props 来为给定路由分配内容:
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 alt="Vue logo" src="./assets/logo.png" width="25%" />
<router-view />
<portal-target name="modal" />
</div>
</template>
<script>
export default {
name: "App",
};
</script>
就是这样