Why do VueJS move animations only work in one direction?

421 views Asked by At

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.

1

There are 1 answers

0
Terry On BEST ANSWER

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>