Vue.use(VueRouter)
const contactGuard = function(to, from, next) {
if (to.name === 'contact') {
this.$root.$emit('modal', true)
next(false)
} else {
next()
}
}
const routes = [{
path: '/',
name: 'home',
component: {
template: `<div><p>Home Page</p></div>`,
beforeRouteLeave: contactGuard
}
},
{
path: '/about',
name: 'about',
component: {
template: `<div><p>About Page</p></div>`,
beforeRouteLeave: contactGuard
}
},
{
path: '/contact',
name: 'contact',
beforeEnter: (to, from, next) => {
if (from.path) {
// we're coming from another page
this.$root.$emit('modal', true)
next(false)
} else {
// we've directly navigated to /contact
next({
replace: true,
path: '/',
query: {
contact: true
}
})
}
}
}
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
next(vm => {
if (to.query.contact) {
vm.$root.$emit('modal', true)
}
})
})
new Vue({
el: '#app',
router,
data() {
return {
modal: false
}
},
mounted() {
this.$on('modal', show => {
this.modal = show
})
}
})
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Foobar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" :to="{ name: 'home' }">Home</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{ name: 'about' }">About</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{ name: 'contact' }">Contact</router-link>
</li>
</ul>
</div>
</nav>
<div class="container">
<router-view></router-view>
</div>
<transition name="modal">
<div class="modal-mask" v-if="modal">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$root.$emit('modal', false)">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</div>