在 Vue 组件渲染上同时过渡多个元素

Transition multiple elements at the same time on Vue component render

以下 jsfiddle 中显示的简单案例:

https://jsfiddle.net/hsak2rdu/

我想交换两个元素并设置动画,但失败了。在playground点击toggle按钮后可以看到,第二个元素闪到最后的位置。

我希望它们同时具有动画效果,就像相互交叉一样。可能吗?

模板:

<div id="app">
  <div class="dom" v-for="(_d, _i) in list" :key="_d.id" :style="{ top: _i * 50 + 'px'}">
    <span>{{_d.text}}{{_i}}</span>
  </div>
  <button @click="handle">Toggle</button>
  {{list}}
</div>

JS:

new Vue({
  el: '#app',
  data: {
    show: true,
    list: [
      {
        id:1,
        text:'First'
      },
      {
        id:2,
        text:'Second'
      }
    ]
  },
  methods:{
    handle: function (){
      console.log("DEBUG", this.list)
      let a = JSON.parse(JSON.stringify(this.list[0]));
      let b = JSON.parse(JSON.stringify(this.list[1]))
      this.$set(this.list, 0, b);
      this.$set(this.list, 1, a);
    }
  }
});

唯一必要的更改是将 v-for 包装在 <transition-group> 中:

<transition-group tag="div" name="list">
  <div class="dom" v-for="(_d, _i) in list" :key="_d.id" :style="{ top: _i * 20 + 'px' }">
    <span>{{_d.text}}{{_i}}</span>
  </div>
</transition-group>

来自docs

This might seem like magic, but under the hood, Vue is using an animation technique called FLIP to smoothly transition elements from their old position to their new position using transforms

这是一个演示:

new Vue({
  el: '#app',
  data: () => ({
    show: true,
    list: [
      {
        id:1,
        text:'First'
      },
      {
        id:2,
        text:'Second'
      }
    ]
  }),
  methods:{
    handle: function (){
      console.log("DEBUG", this.list)
      let a = JSON.parse(JSON.stringify(this.list[0]));
      let b = JSON.parse(JSON.stringify(this.list[1]))
      this.$set(this.list, 0, b);
      this.$set(this.list, 1, a);
    }
  }
});
.dom{
  position: absolute;
  transition: all 1s linear;
  opacity: 1;
}
button{
  margin-top: 50px;
}
#app{
  margin-top: 50px;
  position: relative;
}
<div id="app">
  <transition-group tag="div" name="list">
    <div class="dom" v-for="(_d, _i) in list" :key="_d.id" :style="{ top: _i * 20 + 'px' }">
      <span>{{_d.text}}{{_i}}</span>
    </div>
  </transition-group>
  <button @click="handle">Toggle</button>
  {{list}}
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>