Reputation: 1500
I'm developing a single page application / mobile app, with Vue.JS. I want a slide effect when changing the pages, and I can do it like this:
transition name="slide"
router-view transition
transition
But I wanted the reverse effect of the slide when the user returns the page. In other words, when the user opens a new page, the page will come from the right, but when they go back, the page will come from the left.
There is a plugin for Vue router, called vue-router-transition
, but it does not work. It is out of date, it only works with very old versions of Vue.
Also there is a tutorial on dynamic transitions, but only works when it is parents routes, ex: example.com/rota1/rota2/rota3
, which is not my case.
I thought of the following logic in the before.each.router
, set the transition class (slide-left
or slide-right
) depending on whether the user clicked on a go back button.
The problem is that I do not know how to apply this logic in code. I would have to pass the value of a variable that is in main.js
to app.vue
and I do not know how to do this.
Upvotes: 3
Views: 6500
Reputation: 16513
Hope this helps:
new Vue({
el: '#demo',
data: {
slideTransition: 'slide-left',
showChild: false,
},
watch: {
showChild(value) {
if (value) {
this.setSlideTransition('slide-right');
} else {
this.setSlideTransition('slide-left');
}
},
},
methods: {
setSlideTransition(slideDirection) {
// Note: 300ms mentioned below is matching with css transition timing
setTimeout(() => { this.slideTransition = slideDirection; }, 300);
},
},
});
body {
margin: 0;
color: #bdbdbd;
background-color: #161616;
font-family: Helvetica neue, roboto;
}
.container {
width: 500px;
background: #161616;
}
main {
width: 60%;
height: 300px;
background-color: #333;
}
aside {
width: 40%;
background-color: #555;
}
.container, main, .parent, .child, .content {
display: flex;
align-items: center;
justify-content: center;
}
.parent {
background-color: deepskyblue;
}
.child {
background-color: deeppink;
}
.container, main, aside {
position: relative;
height: 199px;
}
.pin {
top: 0;
left: 0;
right: 0;
bottom: 0;
position: absolute;
}
.pt-50 {
padding-top: 50px;
}
/* transitions */
.fade-enter-active,
.fade-leave-active {
transition-property: opacity;
transition-duration: 0.25s;
}
.fade-enter-active {
transition-delay: 0.25s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
.slide-left-leave-active,
.slide-left-enter-active,
.slide-right-leave-active,
.slide-right-enter-active {
transition: 0.3s;
}
.slide-left-enter {
transform: translate(100%, 0);
}
.slide-left-leave-to {
transform: translate(-100%, 0);
}
.slide-right-enter {
transform: translate(-100%, 0);
}
.slide-right-leave-to {
transform: translate(100%, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo" class="container">
<aside>
<transition name="fade">
<div class="pin parent" v-if="!showChild">
<div>
<h1>Parent</h1>
<a href="#" @click="showChild = true">Go To Child</a>
</div>
</div>
</transition>
<transition :name="slideTransition">
<div class="pin child" v-if="showChild">
<div>
<h1>Child</h1>
<a href="#" @click="showChild = false">Go To Parent</a>
</div>
</div>
</transition>
</aside>
<main>
<div>
<h1>Main</h1>
<transition name="fade">
<div v-if="showChild" class="pin content pt-50" key="child">
<h4>Child Content here</h4>
</div>
<div v-else="" class="pin content pt-50" key="parent">
<h4>Parent Content here</h4>
</div>
</transition>
</div>
</main>
</div>
Upvotes: 2
Reputation: 97
I see 2 options:
@click
method. In the method, first save the variable and then navigate to the link. Check that variable on your beforeRouteUpdate(to, from, next)
method.beforeRouteUpdate(to, from, next)
method that will check on the name of the link (e.g. if you can only go "back" from a certain page, then keep a list of all these type of pages)Upvotes: 1
Reputation: 3536
A while ago I've used the meta
object in vue-router
and added a "fake" depth, because I haven't any children objects. If you use children, then go with this example: https://github.com/vuejs/vue-router/blob/dev/examples/transitions/app.js
export default () => {
return [{
meta: {
depth: 0
},
path: '/home',
component: Home
},
{
meta: {
depth: 1
},
path: '/about',
component: About
}]
}
Now you can check it by your own like this in your App.vue
.
watch: {
$route(to, from) {
const toDepth = to.meta.depth || 0;
const fromDepth = from.meta.depth || 0;
this.transitionName = toDepth >= fromDepth ? 'slide-left' : 'slide-right';
}
}
Upvotes: 2