Asked By: Anonymous
Context:
I have a navigation component which is present on every page but there is a logo element in that component which I am removing based on what route the user is at. I want to add a transition effect to this element when it disappears/appears and I have tried to do so using Vue transitions as you can see down below.
Problem is:
Element only fades in when this.header
goes from false to true – whenever it goes from true to false no animation happens.
You can look at the problem for yourself in this code sandbox
Sidenote:
The CSS is not the problem. I know this because the desired effect works perfectly well if I instead trigger it using a button. The problem seems to have something to do with the nature of using a router change to trigger the animation. Do any of you have any idea why this would be the case?
<template>
<div class="headerNav">
<transition name="fade">
<div class="logo" v-if="!this.logo"></div>
</transition>
</div>
</template>
<script>
export default {
name: 'Navbar',
components: {
postFilter,
},
data() {
return {
logo: null,
}
},
mounted() {
//changing around the header depending on the page we are on so that we can use one header for all pages
if (this.$route.name == 'Library' || this.$route.name == 'Profile') {
this.logo = false
} else {
this.logo = true
}
}
</script>
The CSS (this should not be a problem but I included it anyway)
.fade-enter-active {
transition: all .3s ease;
}
.fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.fade-enter, .fade-leave-to {
transform: translateY(10px); opacity: 0;
}
Solution
Answered By: Anonymous
Based on the comments and codesandboxes, here is a working version: https://codesandbox.io/s/olz3jrk829
Two main changes:
Instead of
<transition name="fade">
<div class="logo" v-if="page"></div>
</transition>
<transition name="fade">
<div class="logo two" v-if="!page"></div>
</transition>
Combine both div
in one transition. Vue needs keys to determine each section:
<transition name="fade">
<div v-if="page" class="logo" key="1">12</div>
<div v-else class="logo two" key="2">34</div>
</transition>
Use the computed
function instead of mounted
:
computed: {
page() {
if (this.$route.name == 'otherpage') {
return false
} else {
return true
}
}
}
Most importantly, you reuse your navigation
in each component (home
and otherpage
in your example), so the leave transition doesn’t get triggered from mounting.
The right way would be to remove the navigation
component from the home
and otherpage
component, so it gets used only once in App.vue
, which let all other components share one navigation
instance.
Here is your original question with the changes:
<template>
<div class="headerNav">
<transition name="fade">
<div v-if="logo" class="logo" key="1"></div>
<div v-else class="logo two" key="2"></div>
</transition>
</div>
</template>
<script>
export default {
name: 'Navbar',
components: {
postFilter,
},
data() {
return {}
},
computed: {
logo() {
if (this.$route.name == 'Library' || this.$route.name == 'Profile') {
return false
} else {
return true
}
}
}
</script>