以动态列表为整体的组过渡

Group transition with dynamic list as a whole

我有一个data_sets。我需要取出某个数据集(片段中的data_source),过滤它(片段中的itemList)并显示它,使用任何简单的组转换,最好是Vue中的list转换official guide


This is a snippet that I created on https://sfc.vuejs.org/ 玩玩。

<template>
  <div>
    <ul>
      <transition-group name="list" mode="out-in">
      <li v-for="item in itemList" :key="item.id">
        {{item.content}}
        </li>
      </transition-group>
    </ul>
  </div>
  
  <button @click="changeDatasource(0)">
    Dataset 1
  </button>
  <button @click="changeDatasource(1)">
    Dataset 2
  </button>
  
  <button @click="changeDatasource(2)">
    Dataset 3
  </button>
</template>

<script>
  export default {
    data() {
      return {
        data_sets: [
          [{
              id: 1,
              content: "Frog",
              active: 1,
            },
            {
              id: 2,
              content: "Elephant",
              active: 0,
            },
            {
              id: 3,
              content: "Racoon",
              active: 1,
            },
            {
              id: 8,
              content: "Cheetah",
              active: 1,
            },
          ],
          [{
              id: 4,
              content: "Rooster",
              active: 1,
            },
            {
              id: 5,
              content: "Cow",
              active: 1,
            },
            {
              id: 6,
              content: "Cat",
              active: 1,
            },
            {
              id: 7,
              content: "Dog",
              active: 0,
            },
          ],
          [{
              id: 10,
              content: "Lion",
              active: 1,
            },
            {
              id: 11,
              content: "Shark",
              active: 1,
            },
            {
              id: 12,
              content: "Bee",
              active: 0,
            },
            {
              id: 13,
              content: "Cockroaches",
              active: 0,
            },
          ],
        ],
        data_source: [],
      }
    },
    computed: {
      itemList: {
        get() {
          return this.data_source.filter((item) => item.active)
        },

        set(newValue) {
          //this.itemList = newValue; <--
        }
      }
    },
    methods: {
      changeDatasource: function(id) {
        //this.itemList = [] <--
        this.data_source = this.data_sets[id];
      }
    }
  }
</script>

<style scoped>
  .list-enter-active,
  .list-leave-active {
    transition: all 0.5s ease;
  }
  
  .list-enter-from,
  .list-leave-to {
    opacity: 0;
    transform: translateX(30px);
  }
</style>


当点击按钮选择数据集时,您可以看到过渡不正常:新项目进来时旧项目仍然存在。预期的顺序应该是:旧项目消失,然后新项目进来.


很有可能是因为itemList是一次整体替换的。所以我尝试:

  1. itemList = [],
  2. 继续进行更改。 (片段中的评论部分)

RangeError: Maximum call stack size exceeded

猜猜它会陷入某种无限循环,在这一点上我完全没有意义。

我也搞过transition mode,也好不到哪里去

我的问题是有什么方法可以像这样将过渡应用于整个列表?

通过使用 setTimeoutsetInterval 解决了它,并将 computed 属性 更改为 watch。 内容转移是有的,但一点 CSS 和 JavaScript 操作将修复它。不是最好的解决方案,但现在这是我能想到的。

Result snippet

<template>
  <div>
    <ul>
      <transition-group name="list">
      <li v-for="item in itemList" :key="item.id">
        {{item.content}}
        </li>
      </transition-group>
    </ul>
  </div>
  
  <button @click="changeDatasource(0)">
    Dataset 1
  </button>
  <button @click="changeDatasource(1)">
    Dataset 2
  </button>
  
  <button @click="changeDatasource(2)">
    Dataset 3
  </button>
</template>

<script>
  export default {
    data() {
      return {
        data_sets: [
          [{
              id: 1,
              content: "Frog",
              active: 1,
            },
            {
              id: 2,
              content: "Elephant",
              active: 0,
            },
            {
              id: 3,
              content: "Racoon",
              active: 1,
            },
            {
              id: 8,
              content: "Cheetah",
              active: 1,
            },
          ],
          [{
              id: 4,
              content: "Rooster",
              active: 1,
            },
            {
              id: 5,
              content: "Cow",
              active: 1,
            },
            {
              id: 6,
              content: "Cat",
              active: 1,
            },
            {
              id: 7,
              content: "Dog",
              active: 0,
            },
          ],
          [{
              id: 10,
              content: "Lion",
              active: 1,
            },
            {
              id: 11,
              content: "Shark",
              active: 1,
            },
            {
              id: 12,
              content: "Bee",
              active: 0,
            },
            {
              id: 13,
              content: "Cockroaches",
              active: 0,
            },
          ],
        ],
        data_source: [],
        itemList: [],
      }
    },
    methods: {
      changeDatasource: function(id) {
        //this.itemList = [] <--
        this.data_source = this.data_sets[id];
      }
    },
    watch: {
      data_source: function(newValue, oldValue) {
        let initialLength = this.itemList.length;
        if (initialLength > 0) {
          this.itemList = [];
        }
        let dataLength = newValue.length;
        let interval = 200;
        let i = 0;
        let timer = setInterval(() => {
          setTimeout(() => {
            if (typeof newValue[i - 1] != 'undefined') {
              this.itemList.push(newValue[i - 1])
            }
          }, interval)
          if (i === dataLength - 1) {
            clearInterval(timer);
          }
          i++;

        }, interval)
      }
    }
  }
</script>

<style scoped>
  .list-enter-active,
  .list-leave-active {
    transition: all 0.5s ease;
  }
  
  .list-enter-from,
  .list-leave-to {
    opacity: 0;
    transform: translateX(30px);
  }
</style>