vue.js wrong transition group animation position
There is a bug in transition-group
!
When you bind the key
of li
as the index
, every time you remove a li
, the animation always happend at the last li
element.
So, if you want to use the animation with li
, you can bind the key
with number
in your case.
<transition-group name="mix"
mode="out-in">
<li class="alert alert-success list-unstyled"
style="height: 40px; padding: 10px 15px;margin-bottom: 8px;cursor: pointer;"
v-for="(number,index) in myNumbers"
@click="removeNumber(index)"
:key="index">
{{number}}
</li>
</transition-group>
vs
<transition-group name="mix"
mode="out-in">
<li class="alert alert-success list-unstyled"
style="height: 40px; padding: 10px 15px;margin-bottom: 8px;cursor: pointer;"
v-for="(number,index) in myNumbers"
@click="removeNumber(index)"
:key="number">
{{number}}
</li>
</transition-group>
Finally, if you use animation with transition-group
, do not bind the key
to index
, instead of item
or number
(in your case).
No matter what , make sure the key
has the unique value.
Solution
Don't use index anywhere in the v-bind:key when using transition or transition-group.
Explanation
There is a bug/missing documentation, as well as bad documentation in the cookbook on vuejs.org, but there's a detailed explanation in the comments [1] on how indexes work, but no recognition this is a problem for developers in it's current state.
I have posted a few times to github, but the Vue.js developers there seem dismissive at best and refuse to either document this behavior or recognize this as a problem.
Reproduction of bug/error
There are three examples in the codepen below. The #1 works, the #2 uses :key="index" (your specific error above) and #3 uses :key="item +'_'+ index".
#2 and #3 give the error you are experiencing.
https://codepen.io/megacromulent/pen/wEzWNL
Summary of codepen:
This one works: (using item as :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="item">
{{item}}
</li>
</transition-group>
This one fails: (using index as :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="index" >
{{item}}
</li>
</transition-group>
This one fails worse: (concatenating index with string in :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="item + '_' + index" >
{{item}}
</li>
</transition-group>
Bug report (rejected)
I submitted this bug report to Vue.js devs here:
"Transition-group animates only last element if using index as the key"
https://github.com/vuejs/vue/issues/8718
It got closed instantly, so based on their input (requested I do a PR for comment, but that is not in my wheelhouse) I followed up with this feature request for the dev build to give an error, which would solve the problem at it's root.
Feature request (follow up, also rejected)
"Dev build console error when using index in :key value with v-for and transitions"
https://github.com/vuejs/vue/issues/8730
It seems reasonable to put a dev error on this issue, but the vue.js developers seem to think we should be able to figure this out on our own. I hope they come around and see this as a real issue. It's cost me hours of testing and reporting time to figure out.
I hope this helps other devs wasting time with this issue.
References
[1] https://github.com/vuejs/vue/issues/8718#issuecomment-416909724