I'm learning Vue and very confused about this.
I'm trying to replicate jQuery's slideToggle()
.
I have a list of items, each with a heading and a body.
Initially the body of each list item is hidden, and when the user clicks the title it should do a slide transition.
Because the body of each list item is a variable height, I need to do this in JS, because CSS can't correctly do the transition for height: auto
. (Even max-height
is far from smooth.
So I'm using the Velocity.js library, and slideDown
is perfect. slideUp
can't run because (I think) Vue has already hidden the element.
Here's the (simplified) template:
<ul class="list-group">
<li class="list-group-item" v-for="word in saved_definitions">
<h3 @click="word.show = !word.show">
{{ word.word }}
</h3>
<transition v-on:before-enter="slide_down" v-on:before-leave="slide_up" :css="false">
<div v-show="word.show">
{{ word.definition }}
</div>
</transition>
</li>
</ul>
saved_definitions
is an array of {word: '', definition: '', show: true}
objects.
Here are the relevant methods:
slide_down: function(el) {
Velocity(el, 'slideDown', 'fast');
},
slide_up: function(el) {
console.log(el);
Velocity(el, 'slideUp', 'fast');
}
slide_down()
is working perfectly.
slide_up()
doesn't work, the definition disappears with no transition. The console.log()
shows that the element has display: none
before Velocity can do the slideUp
.
jsFiddle is here: https://jsfiddle.net/zmoc2v3n/ - you can see slideDown is smooth, slideUp doesn't work.
I've tried the leave
and after-leave
hooks, which don't help.
And if I use v-if
, I see the element get rendered first, then hidden, and then slideDown happens. I still have the same issue with before-leave
hiding the element immediately.
Thanks in advance for your help!
I asked this question on the Vue Forum, and thought I'd post the answer here.
Try using the enter and leave events instead, as they allow you to let Vue know when your animation is finished.
<transition @enter="slide_down" @leave="slide_up"></transition>
In the js:
function slide_down(el, done) {
Velocity(el, 'slideDown', {
duration: 'fast',
complete: done
})
}
function slide_up(el, done) {
Velocity(el, 'slideUp', {
duration: 'fast',
complete: done
})
}
Turns out my issue was more with Velocity than Vue.