VueJS: Complete dynamic component transition before rendering new component
mode="out-in"
should be what you want.
Transition between the same component?
Had the same problem yesterday! ^^"
It worked fine when I added a :key="" attribute to my component (even if there is no prop called key in the child component).
Try with this :
<transition name="slide">
<my-component :key="currentIndex" :my-prop="data[currentIndex]" />
</transition>
I don't know yet why but I guess if a prop is an object, it dont detect the changes? Or maybe you must pass a key attribute (but I saw some examples not using key attribute...)
Tell me if it works ;)
Edit: I saw that you change the name of the transition and the style don't include this name. Try the solution above with the default name and style ("fade") https://v2.vuejs.org/v2/guide/transitions.html
Vue.js change a leave transition dynamically after enter has been played
Looks like your slide transition starts before slideDirection is updated.
Try using nextTick function so that slide transition wait for direction to get updated.
Updated Example.
new Vue({ el: "#app", data: { slideDirection: "right", counter: 0 }, methods: { moveRight: function() { this.slideDirection = "right"; this.$nextTick(() => { this.counter++; })
}, moveLeft: function() { this.slideDirection = "left"; this.$nextTick(() => { this.counter--; }) }, }})
body { background: #20262E; padding: 20px; font-family: Helvetica;}
#app { background: #fff; border-radius: 4px; padding: 20px; transition: all 0.2s; display: flex; flex-direction: column; width: 300px; height: 150px;}
div#slider { position: relative;}
div#slider div:nth-child(even) { background: green;}
div#slider div:nth-child(odd) { background: red;}
div { padding: 30px; width: 100%; height: 100%; position: absolute;}
div:odd { background: blue;}
.slider-right-enter { opacity: 0; transform: translatex(100%);}
.slider-right-enter-to { opacity: 1; transition: all 0.5s ease-out;}
.slider-right-leave-to { opacity: 0; transform: translatex(-100%); transition: all 0.5s ease-out;}
.slider-left-enter { opacity: 0; transform: translatex(-100%);}
.slider-left-enter-to { opacity: 1; transition: all 0.5s ease-out;}
.slider-left-leave-to { opacity: 0; transform: translatex(100%); transition: all 0.5s ease-out;}
<div id="app">
<div id="slider"> <transition v-bind:name="'slider-' + slideDirection"> <div v-if='counter == 0'> 0 </div> </transition>
<transition v-bind:name="'slider-' + slideDirection"> <div v-if='counter == 1'> 1 </div> </transition>
<transition v-bind:name="'slider-' + slideDirection"> <div v-if='counter == 2'> 2 </div> </transition>
<transition v-bind:name="'slider-' + slideDirection"> <div v-if='counter == 3'> 3 </div> </transition>
</div>
<div>
<button @click="moveLeft"> << </button> <button @click="moveRight"> >> </button> </div></div>
Dynamic style for Vue transition
First, your way to set style just not work
el.style = {
transition: 'all 0.6s',
marginLeft: '-20em',
};
I just move transition: 'all 0.6s'
to css and set style like this
el.style.marginLeft = '-20em';
Second, enter
event is called very soon after beforeEnter
event so the browser cannot detect change between two states. So I wrap enter
event into setTimeout
to make a trick to trigger the transition.
Third, done
callback is not necessary in this case. It's only required in pure js transition. We are using mixed CSS and JS
Vue.component('app', { template: `<div class="app"> <sidebar>sidebar content</sidebar> <div class="main">Hello, VueJS!</div> </div>`});
Vue.component('sidebar', { template: ` <div class="sidebarContainer"> <transition name="slide" @before-enter="beforeEnter" @enter="enter" @leave="leave" > <div v-if="isOpen" class="sidebar" :style="{ width }"> <slot/> </div> </transition> <div class="toggle" @click="isOpen = !isOpen"><></div> </div>`, props: { 'width': { default: '20em', } }, data() { return { isOpen: true, }; }, methods: { beforeEnter(el) { el.style.marginLeft = '-20em'; }, enter(el, done) { // Wait a tick here, so browser can detect style change and tigger transition setTimeout(() => { el.style.marginLeft = '0'; }, 0) }, leave(el, done) { el.style.marginLeft = '-20em'; }, },});
new Vue({ el: '#app', template: '<app/>'});
html,body,.app { height: 100%;}
.app { display: flex;}
.main { flex-grow: 1; background: red;}
.sidebarContainer { display: flex;}
.sidebar { flex-grow: 1; padding: 0.5em; background: blue; transition: all 0.6s;}
.toggle { margin: 0.5em;}
<div id="app"></div><script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
How do you realize the in-out mode transition effect when using dynamic route matching in Vue.js?
You can definitely use in-out
with router-view
, Here is the modified fiddle from the question you have added : https://jsfiddle.net/dLnz4rbL/3/
I have change the transition to slide-fade
with below CSS:
/* Enter and leave animations can use different */
/* durations and timing functions. */
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for <2.1.8 */ {
transform: translateX(500px);
opacity: 0;
}
Related Topics
Refinerycms 2.1.0 and Zurb 4 Top Menu with Dropdown Navigation
Using CSS Mix-Blend-Mode with a Child of a Position Fixed Element
Place Custom Checkbox Icon to Right of Label Bootstrap 4
Wkhtmltopdf CSS Sizes in Cm/Mm
Run CSS File Through Twig When Using {% Stylesheets %} Tag in Twig with Symfony2
CSS Col Visibility:Collapse Does Not Work on Chrome
Position a Image Over Another Existing '<Img />' in CSS
How to Center Text Inside: Before Pseudo Element
Block Elements Only Inside Flex Item
Is Using @Import Declarations a Bad Practice
Styling Kml with CSS in Google Maps V3
Selecting Children Elements But Not Grandchildren
Hiding Text Using "Text-Indent"