# 1.transition 基本用法

  • v-enter-from:定义进入过渡的开始状态。在原始被插入之前生效,在元素被插入之后的下一帧移除。
  • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡 / 动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  • v-enter-to:定义进入过渡的介绍状态。在元素被插入之后下一帧生效 (与此同时 v-enter-from 被移除),在过渡 / 动画完成之后移除
  • v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡 / 动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  • v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave-from 被删除),在过渡 / 动画完成之后移除。
  • class 的 name 命名规则:
    • 如果我们使用的是一个没有 name 的 transition,那么所有的 class 是以 v- 做为默认前缀;
    • 如果我们添加了一个 name 属性,比如 <transitions name:"neko">, 那么所有的 class 会以 neko- 开头;
  • 执行顺序:

transition_enter_leave

  • type:Vue 为了指定过渡的完成,内部是在监听 transitionend 或 animationend,到底使用哪一个取决于元素应用的 CSS 规则:
    • 如果只使用了其中的一个,那么 Vue 能自动失败类型并设置监听;
    • 但如果同时使用:可能某一个动画执行结束时,另外一个动画还没有结束,可以设置 type 属性为 animation 或者 transition 来明确告知 Vue 监听的类型
  • duration:可以设置两种类型的值
    • number 类型:同时设置进入和离开的过渡时间;
    • object 类型:分别设置进入和离开的过渡时间;
  • mode:
    • in-out:上个要消失的元素或组件先消失,等到消失完之后,下一个组件或者元素再进入。
    • out-in:下一个要出现的组件或者元素先进入,等到进入完之后,上一个组件或者元素再消失。
  • appear:页面初始化时就默认执行一次动画。只写 appear 属性不赋值默认为 true

# 2.transition 基本使用

vue
// App.vue
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition name="neko"> //定义 class name 名
      <h3 v-if="isShow">Hello World!</h3>
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
/* 进入过渡开始的状态 */
.neko-enter-from {
  opacity: 0;
}
/* 进入过渡生效的状态 */
.neko-enter-active {
  transition: opacity 1s ease;
}
/* 进入过渡结束的状态 */  
.neko-enter-to {  
  opacity: 1; /* 浏览器显示默认为 1,可省略不写 */
}
/* 离开过渡开始的状态 */
.neko-leave-from {
  opacity: 1; /* 可不写 */
}
/* 离地过渡生效的状态 */
.neko-leave-active {
  transition: opacity 1s ease;
}
/* 离过渡结束的状态 */
.neko-leave-to {
  opacity: 0;
}
</style>

参考结果:

transition_class

# 3.animation 定义动画

vue
// App.vue
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition name="neko">
      <h3 class="title" v-if="isShow">你好呀,李银河!</h3>
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
.title {
  display: inline-block;
  background-color: pink;
}
.neko-enter-active {
  animation: bounce 1s ease;
}
.neko-leave-active {
  animation: bounce 1s ease reverse;
}
@keyframes bounce {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

参考结果:

transition_animation

# 4. type & duration

vue
// App
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition
      name="neko"
      type="transition"
      :duration="{ enter: 4000, leave: 1000 }"
    >
      <h3 class="title" v-if="isShow">你好呀,李银河!</h3>
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
.title {
  display: inline-block;
  background-color: pink;
}
/* 因为设置了 type 和 duration 属性, 所以会以不超出动画设置的时间为前提,优先执行 type 和 duration 里面定义的方式与时间。比如 {enter: 1000, leave: 1000} 这种就不能达到满足的效果 ,会得到执行的效果是 animation 执行 1s 的结果。而如果自己定义的时间进入和离开 { enter: 5000, leave: 5000 } 都比 animation 定义的时间长,则会隐藏失效 */
.neko-enter-active {
  animation: bounce 3s ease;
}
.neko-leave-active {
  animation: bounce 3s ease reverse;
}
@keyframes bounce {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

参考结果:

transition_type_duration

# 5.mode 元素切换顺序

vue
// App.vue
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition
      name="neko"
      type="transition"
      :duration="{ enter: 1000, leave: 1000 }"
      mode="out-in"
    >
      <h3 class="title" v-if="isShow">你好呀,李银河!</h3>
      <h3 class="title" v-else>Hello World!</h3>
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
.title {
  display: inline-block;
  background-color: pink;
}
.neko-enter-active {
  animation: bounce 1s ease;
}
.neko-leave-active {
  animation: bounce 1s ease reverse;
}
@keyframes bounce {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

参考结果:out-in 先等你好呀,李银河!消失,再让 Hello World!显示

transition_mode

# 6.component 切换

# Home

vue
<template>
  <div>
    <span>我是Home组件</span>
  </div>
</template>
<script>
export default {};
</script>
<style scoped></style>

# About

vue
<template>
  <div>
    <span>我是About组件</span>
  </div>
</template>
<script>
export default {};
</script>
<style scoped></style>

# App1

vue
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition
      name="neko"
      type="transition"
      :duration="{ enter: 1000, leave: 1000 }"
      mode="out-in"
    >
      <component :is="isShow ? 'home' : 'about'"></component>
    </transition>
  </div>
</template>
<script>
import Home from "./Home";
import About from "./About";
export default {
  components: {
    Home,
    About,
  },
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
.title {
  display: inline-block;
  background-color: pink;
}
.neko-enter-active {
  animation: bounce 1s ease;
}
.neko-leave-active {
  animation: bounce 1s ease reverse;
}
@keyframes bounce {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

参考结果:

transition_component

# App2

vue
<template>
  <div class="app">
    <div><button @click="isShow = !isShow">显示/隐藏</button></div>
    <transition
      name="neko"
      type="transition"
      :duration="{ enter: 1000, leave: 1000 }"
      mode="out-in"
      appear
    >
      <component :is="isShow ? 'home' : 'about'"></component>
    </transition>
  </div>
</template>
<script>
import Home from "./Home";
import About from "./About";
export default {
  components: {
    Home,
    About,
  },
  data() {
    return {
      isShow: true,
    };
  },
};
</script>
<style scoped>
.title {
  display: inline-block;
  background-color: pink;
}
.neko-enter-active {
  animation: bounce 1s ease;
}
.neko-leave-active {
  animation: bounce 1s ease reverse;
}
@keyframes bounce {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
</style>

参考结果:

transition_appear