Reputation: 375
I encounter with transition issue when animation when clicked on 'stream' button is different from animation after click on 'stream random' button from jsfiddle bellow.
Maybe I'm wrong with styling but could not realize why still getting the stream behaviour.
I need behaviour as on 'stream random' for array of div's.
Thank you
new Vue({
el: '#list-complete-demo',
data: {
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
add: function (item) {
this.items.splice(this.items.length, 0, item)
},
remove: function () {
return this.items.splice(0, 1)[0]
},
stream: function () {
this.add(this.remove())
},
streamrnd: function () {
this.add(this.nextNum++)
this.remove()
}
}
})
.list-complete-item {
transition: all 1s;
display: inline-block;
margin-right: 10px;
border: 1px solid green;
padding: 10px 10px 10px 10px;
}
.innerDiv {
border: 1px solid red;
}
.list-complete-enter {
opacity: 0;
transform: translateX(40px);
}
.list-complete-leave-to {
opacity: 0;
transform: translateX(-40px);
}
.list-complete-leave-active {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.js"></script>
<div id="list-complete-demo">
<button v-on:click="stream">Stream</button>
<button v-on:click="streamrnd">Stream Random</button>
<transition-group
name="list-complete"
tag="div"
style="margin-top: 50px">
<div
v-for="item in items"
:key="item"
class="list-complete-item">
<div class='innerDiv'>{{ item }}</div>
</div>
</transition-group>
</div>
Upvotes: 1
Views: 588
Reputation: 34286
You have keyed the transition elements by the item itself, which is a number.
When you click the stream button, you're removing the last item from the array and inserting it at the beginning of the array. Since the key is the same for that item, Vue has detected that the item was moved in the array and transitions it as such.
When you click the stream random button, you are removing the last item from the array and inserting a new unique item with a different key than the existing items in the DOM. Vue will perform a leave transition for the removed item and an enter transition for the new item.
You need to use key
to control how Vue reuses DOM elements for your items.
You can associate a unique numerical key for each item in your array to prevent Vue from reusing the spans:
<span v-for="item in items" :key="item.key">{{ item.value }}</span>
data: {
items: [
{ key: 1, value: 1 },
{ key: 2, value: 2 },
{ key: 3, value: 3 },
{ key: 4, value: 4 },
{ key: 5, value: 5 },
{ key: 6, value: 6 },
{ key: 7, value: 7 },
{ key: 8, value: 8 },
{ key: 9, value: 9 },
],
nextNum: 10,
nextKey: 10
},
methods: {
add(item) {
this.items.splice(0, 0, {
key: this.nextKey++,
value: isNaN(item) ? this.nextNum++ : item,
})
},
remove() {
return this.items.splice(this.items.length - 1, 1)[0].value
},
stream() {
this.add(this.remove())
},
streamrnd() {
this.add(this.nextNum++)
this.remove()
}
}
Obviously you can simplify that code, but you get the idea.
Upvotes: 1
Reputation: 25221
In the stream function, you are adding the element that was removed back into the array. So the animation moves it from the end to the start.
In the streamrnd function you are just removing it entirely, and adding a new one. So it animates accordingly.
Upvotes: 1