0

I'm entirely stumped by this. For some reason, Vue3 will correctly apply the move animation class for a <transition-group/> containing a list of items, but only if the list is advanced forward. I've put together a CodePen for this and even with a very simple use case (listing numbers), the transition classes just don't get applied if you advance in any direction except backwards.

https://codepen.io/monitorjbl/pen/vYZPzXO

If you click the "-" button, the animation classes will be applied and you can see the move animations fire. However, clicking the "+" button results in no move animation classes being applied and no animation at all.

monitorjbl
  • 4,280
  • 3
  • 36
  • 45
  • See docs https://vuejs.org/v2/guide/transitions.html#List-Entering-Leaving-Transitions – Nick Sep 30 '21 at 20:47
  • I've read through this a few times, so it's certainly possible I'm missing something but I don't know what. Any hints? – monitorjbl Sep 30 '21 at 20:48
  • You’re missing the enter and leave CSS classes. – Terry Sep 30 '21 at 20:51
  • @Terry I'm asking about move animations, so I'm not sure what enter and leave CSS classes are required. The move animations work in one direction and not the other, is there some kind of default enter/leave class that's accounting for that? – monitorjbl Sep 30 '21 at 20:57
  • You’re only moving the elements in the middle. The first and last elements are be destroyed or re-rendered depending on the direction of shifting. You can see them being removed or added to the DOM, especially if you use a slower transition duration. – Terry Sep 30 '21 at 21:14
  • @Terry Yeah, the move animation is applied to the elements in the middle in one direction, but not the other. The elements at the ends are entering/leaving with no animation, as expected but the interior elements should be animated in either direction. I'll update my codepen to make the move happen slower to make it more obvious that it doesn't work when you hit the "+" button. – monitorjbl Sep 30 '21 at 21:36

1 Answers1

1

As I have mentioned in your comments, you are missing the enter and leave transition classes. Since you are only changing 3 elements of the array at any time, that means that 2 elements will remain in the list and will match your "move" class, but the 3 elements will be created/destroyed and you are not handling those cases.

If you refer to the example given in the Vue documentation, you can see that enter/leave transition classes are needed to pull everything together. For example, you can add this to your CSS:

.flip-list-enter-from,
.flip-list-leave-to {
  opacity: 0;
}

.flip-list-leave-active {
  position: absolute;
}

Here is a proof-of-concept example:

const Demo = {
  data() {
    return {
      min: 1,
      max: 5,
      list: []
    };
  },
  mounted() {
    this.populateList();
  },
  methods: {
    shiftDown() {
      this.min -= 3;
      this.max -= 3;
      this.populateList();
    },
    shiftUp() {
      this.min += 3;
      this.max += 3;
      this.populateList();
    },
    populateList() {
      this.list = [];
      for (let i = this.min; i <= this.max; i++) {
        this.list.push(i);
      }
    }
  }
};

Vue.createApp(Demo).mount("#flip-list-demo");
body {
  margin: 30px;
}

.flip-list-item {
  transition: all 0.8s ease;
}

.flip-list-enter-from,
.flip-list-leave-to {
  opacity: 0;
}

.flip-list-leave-active {
  position: absolute;
}
<script src="https://unpkg.com/vue@next"></script>
<div id="flip-list-demo">
  <button @click="shiftDown" style="background-color:cyan">-</button>
  <button @click="shiftUp" style="background-color:yellow">+</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in list" :key="item" class="flip-list-item">
      {{ item }}
    </li>
  </transition-group>
</div>
Terry
  • 63,248
  • 15
  • 96
  • 118