Vue.js 中不需要的动画错误

Unwanted animation bug in Vue.js

这是一个不需要的动画错误,看起来很正常,但我希望 <input v-model="todo"/> 中的元素具有动画效果。问题是每次我按 add 按钮添加 todo 名称 (<input v-model="todo"/>),最后一个元素 'last' 运行动画。

P.s。我尽量保持代码简单。

Vue.createApp({
  data() {
    return {
      todo: "",
      todo_list: ['last'],
    };
  },

  methods: {
    add() {
      this.todo_list.unshift(this.todo);
      console.log(this.todo_list);
    },
    remove(index) {
      this.todo_list.splice(index, 1);
    },
  },
}).mount('#app');
.list-enter-active,
.list-leave-active {
    transition: all 200ms ease-out;
}

.list-enter-from {
    transform: translateY(-20px);
}

.list-leave-to {
    opacity: 0;
    transform: translateX(20px);
}

article {
    width: 50%;
    padding: 10px;
    background-color: #dddddd;
    border: 1px solid #cfcfcf;
    border-radius: 5px;
    margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>

<div id="app">
  <input type="text" v-model="todo" /> <button @click="add">add</button>
  <transition-group name="list" tag="section">
    <article v-for="(todo, index) in todo_list" :key="index" @click="remove(index)">
      <span>{{ todo }}</span>
    </article>
  </transition-group>
</div>

您遇到此问题的原因是您将 index 用作 key。 如果您将元素添加到列表的末尾,那就没问题了。 但由于您将它添加到开头,它会导致您看到的问题。

我建议您让每个 todo 成为一个对象,并为每个对象添加一个唯一标识符。这可以是您递增的简单整数。然后你可以使用 属性 作为 key.

例子

let id = 1;

Vue.createApp({
  data() {
    return {
      todo: "",
      todo_list: [{
        id: id++,
        value: 'last'
      }],
    };
  },

  methods: {
    add() {
      const todo = {
        id: id++,
        value: this.todo
      }
      this.todo_list.unshift(todo);
    },
    remove(index) {
      this.todo_list.splice(index, 1);
    },
  },
}).mount('#app');
.list-enter-active,
.list-leave-active {
  transition: all 200ms ease-out;
}

.list-enter-from {
  transform: translateY(-20px);
}

.list-leave-to {
  opacity: 0;
  transform: translateX(20px);
}

article {
  width: 50%;
  padding: 10px;
  background-color: #dddddd;
  border: 1px solid #cfcfcf;
  border-radius: 5px;
  margin-block: 10px
}
<script src="https://unpkg.com/vue@next"></script>

<div id="app">
  <input type="text" v-model="todo" /> <button @click="add">add</button>
  <transition-group name="list" tag="section">
    <article v-for="(todo, index) in todo_list" :key="todo.id" @click="remove(index)">
      <span>{{ todo.value }}</span>
    </article>
  </transition-group>
</div>