[Vuejs]-What causes the animation to fail in this Vue 3 application?

1๐Ÿ‘

I use an Todo app as an example in composition api way with vue-cli

// driectory: src/components/Todos.vue

<template>
  <div class="todos">
    <input
      type="text"
      v-model="newTodo"
      @keypress.enter="addTodo"
      placeholder="Add a new todo..."
    />
    <transition name="switch" mode="out-in">
      <div v-if="todos.length">
        <transition-group tag="ul" name="list" appear>
          <li v-for="todo in todos" :key="todo.id" @click="deleteTodo(todo.id)">
            {{ todo.text }}
          </li>
        </transition-group>
      </div>
      <div v-else>Woohoo, nothing left todo!</div>
    </transition>
  </div>
</template>

<script>
import { ref } from "vue";

export default {
  setup(props, { emit }) {
    const todos = ref([
      { text: "make the bed", id: 1 },
      { text: "play video games", id: 2 },
    ]);
    const newTodo = ref("");

    const addTodo = () => {
      if (newTodo.value) {
        const id = Math.random();
        todos.value = [{ text: newTodo.value, id }, ...todos.value];
        newTodo.value = "";
      } else {
        emit("badValue");
      }
    };

    const deleteTodo = (id) => {
      todos.value = todos.value.filter((todo) => todo.id != id);
    };

    return { todos, addTodo, deleteTodo, newTodo };
  },
};
</script>

<style>
.todos {
  max-width: 400px;
  margin: 20px auto;
  position: relative;
}
input {
  width: 100%;
  padding: 12px;
  border: 1px solid #eee;
  border-radius: 10px;
  box-sizing: border-box;
  margin-bottom: 20px;
}
.todos ul {
  position: relative;
  padding: 0;
}
.todos li {
  list-style-type: none;
  display: block;
  margin-bottom: 10px;
  padding: 10px;
  background: white;
  box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  width: 100%;
  box-sizing: border-box;
}
.todos li:hover {
  cursor: pointer;
}

/* list transitions */
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: scale(0.6);
}
.list-enter-active {
  transition: all 0.4s ease;
}
.list-leave-active {
  transition: all 0.4s ease;
  position: absolute;
}
.list-leave-to {
  opacity: 0;
  transform: scale(0.6);
}
.list-move {
  transition: all 0.3s ease;
}

/* switch transitions */
.switch-enter-from,
.switch-leave-to {
  opacity: 0;
  transform: translateY(20px);
}
.switch-enter-active
.switch-leave-active {
  transition: all 0.5s ease;
}
</style>

// directory: src/views/Home.views

<template>
  <div class="home">
    <Todos />
  </div>
</template>

<script>
import Todos from "../components/Todos";

export default {
  components: { Todos }
};
</script>

<style scoped>
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 2s ease;
}
</style>

1๐Ÿ‘

The <transition-group> has a tag prop that specifies the element to render. Use that prop with tbody in your table:

<!-- <tbody name="users-table" is="transition-group"> --> โŒ

<transition-group name="users-table" tag="tbody"> โœ…

And the basename of the CSS class for the animation must match the name prop of <transition-group>: users-table (not of the class of the item being animated). Further, the transition class names must be used in the class names:

.users-table-enter-active,
.users-table-leave-active {
  transition: all 1s ease;
}
.users-table-enter-from,
.users-table-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

demo

Leave a comment