Vue 3 第十四章:组件五(内置组件-transition&transition-group)


在Vue3中,内置了许多组件,可以帮助我们更方便地开发应用程序。在本篇博客中,我们将介绍 transition& transition-group组件,以及它们的用法。

1. transition组件

<transition>组件用于在元素插入或删除时添加过渡效果。例如,当我们在一个列表中添加或删除项目时,可以使用<transition>组件为这些操作添加一个动画效果。具体用法如下:

1.1. 基本用法

<template>
  <div>
    <button @click="show = !show">显示/隐藏</button>
    <transition>
      <div v-if="show">Hello, World!</div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
const show = ref(false)

</script>

<style scoped>
.v-enter-active,
.v-leave-active {
      
      
  transition: opacity 2s ease;
}

.v-enter-from,
.v-leave-to {
      
      
  opacity: 0;
}
</style>

在上面的代码中,我们使用<transition>组件将<div>元素包裹起来。当条件showtrue时,<div>元素会被插入到DOM中,并且会显示一个过渡动画。当条件showfalse时,<div>元素会从DOM中删除。

1.2. css过渡class介绍

未命名时一共有 6 个应用于进入与离开过渡效果的 CSS class。
在这里插入图片描述

  • v-enter-from:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。

  • v-enter-active:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。

  • v-enter-to:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是 v-enter-from 被移除的同时),在过渡或动画完成之后移除。

  • v-leave-from:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。

  • v-leave-active:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。

  • v-leave-to:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是 v-leave-from 被移除的同时),在过渡或动画完成之后移除。

1.3. 过渡效果命名

对于一个有名字的过渡效果,对它起作用的过渡 class 会以其名字而不是v作为前缀。下面是一个过渡命名的例子:

1.3.1. 基本用法

<template>
  <div>
    <button @click="show = !show">显示/隐藏</button>
    <transition name="hide">
      <div v-if="show">Hello, World!</div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
const show = ref(false)

</script>

<style scoped>
.hide-enter-active,
.hide-leave-active {
      
      
  transition: opacity 2s ease;
}

.hide-enter-from,
.hide-leave-to {
      
      
  opacity: 0;
}
</style>

注意:<Transition> 一般都会搭配原生 CSS 过渡一起使用,正如上面的例子中所看到的那样。这个transition CSS属性是一个简写形式,使我们可以一次定义一个过渡的各个方面,包括需要执行动画的属性持续时间速度曲线

1.4. 配合自定义动画(animation)使用

原生 CSS 动画CSS transition的应用方式基本上是相同的,只有一点不同,那就是*-enter-from不是在元素插入后立即移除,而是在一个animationend事件触发时被移除。

对于大多数的 CSS 动画,我们可以简单地在 *-enter-active *-leave-active class下声明它们。下面是一个示例:

<template>
  <div>
    <button @click="show = !show">显示/隐藏</button>
    <transition name="hide">
      <div v-if="show">Hello, World!</div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';
const show = ref(false)

</script>

<style scoped>
.hide-enter-active {
      
      
  animation: scsle-in 0.5s;
}

.hide-leave-active {
      
      
  animation: scsle-in 0.5s reverse;
}
@keyframes scsle-in {
      
      
  0% {
      
      
    transform: scale(0);
  }
  50% {
      
      
    transform: scale(1.25);
  }
  100% {
      
      
    transform: scale(1);
  }
}
</style>

1.5. 自定义过渡 class

可以向<Transition>传递以下的 props 来指定自定义的过渡 class:

  • enter-from-class
  • enter-active-class
  • enter-to-class
  • leave-from-class
  • leave-active-class
  • leave-to-class

传入的这些 class 会覆盖相应阶段的默认 class 名。这个功能在你想要在 Vue 的动画机制下集成其他的第三方 CSS 动画库时非常有用,比如 Animate.css

<template>
	<button @click="show = !show">Toggle</button>
  <Transition
    name="custom-classes"
    enter-active-class="animate__animated animate__tada"
    leave-active-class="animate__animated animate__bounceOutRight"
  >
    <p v-if="show">hello</p>
  </Transition>
</template>

<script setup>
import {
      
       ref } from 'vue'

const show = ref(true)
</script>

<style>
@import "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css";
</style>

1.6. <Transition>组件生命周期

<Transition
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @after-enter="onAfterEnter"
  @enter-cancelled="onEnterCancelled"
  @before-leave="onBeforeLeave"
  @leave="onLeave"
  @after-leave="onAfterLeave"
  @leave-cancelled="onLeaveCancelled"
>
  <!-- ... -->
</Transition>
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {
    
    }

// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
    
    
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 当进入过渡完成时调用。
function onAfterEnter(el) {
    
    }
function onEnterCancelled(el) {
    
    }

// 在 leave 钩子之前调用
// 大多数时候,你应该只会用到 leave 钩子
function onBeforeLeave(el) {
    
    }

// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
    
    
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {
    
    }

// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {
    
    }

1.7. transition 常用场景

  • 可复用过渡效果

vue中过渡效果是可以被封装复用的。要创建一个可被复用的过渡,我们需要为<Transition>组件创建一个包装组件,并向内传入插槽内容:

<!-- MyTransition.vue -->
<script>
// JavaScript 钩子逻辑...
</script>

<template>
  <!-- 包装内置的 Transition 组件 -->
  <Transition
    name="my-transition"
    @enter="onEnter"
    @leave="onLeave">
    <slot></slot> <!-- 向内传递插槽内容 -->
  </Transition>
</template>

<style>
/*
  必要的 CSS...
  注意:避免在这里使用 <style scoped>
  因为那不会应用到插槽内容上
*/
</style>

现在MyTransition可以在导入后像内置组件那样使用了:

<MyTransition>
  <div v-if="show">Hello</div>
</MyTransition>
  • 出现时过渡

如果你想在某个节点初次渲染时应用一个过渡效果,你可以添加 appear prop

<Transition appear>
  ...
</Transition>
  • 元素间过渡

除了通过v-if / v-show切换一个元素,我们也可以通过v-if / v-else / v-else-if在几个组件间进行切换,只要确保任一时刻只会有一个元素被渲染即可:

<Transition>
  <button v-if="docState === 'saved'">Edit</button>
  <button v-else-if="docState === 'edited'">Save</button>
  <button v-else-if="docState === 'editing'">Cancel</button>
</Transition>
  • 过渡模式

在之前的例子中,进入和离开的元素都是在同时开始动画的,因此我们不得不将它们设为position: absolute以避免二者同时存在时出现的布局问题。

然而,很多情况下这可能并不符合需求。我们可能想要先执行离开动画,然后在其完成之后再执行元素的进入动画。手动编排这样的动画是非常复杂的,好在我们可以通过向<Transition>传入一个mode prop来实现这个行为:`

<Transition mode="out-in">
  ...
</Transition>
  • 组件间过渡

<Transition>也可以作用于动态组件之间的切换:

<Transition name="fade" mode="out-in">
  <component :is="activeComponent"></component>
</Transition>
  • 动态过渡

<Transition>props (比如 name)也可以是动态的!这让我们可以根据状态变化动态地应用不同类型的过渡:

<Transition :name="transitionName">
  <!-- ... -->
</Transition>

这个特性的用处是可以提前定义好多组 CSS 过渡或动画的 class,然后在它们之间动态切换。

2. transition-group组件

<TransitionGroup> 支持和<Transition>基本相同的 propsCSS 过渡 class JavaScript 钩子监听器,但有以下几点区别:

  • 默认情况下,它不会渲染一个容器元素。但你可以通过传入tag prop来指定一个元素作为容器元素来渲染。

  • 过渡模式在这里不可用,因为我们不再是在互斥的元素之间进行切换。

  • 列表中的每个元素都必须有一个独一无二的 key attribute

  • CSS 过渡class会被应用在列表内的元素上,而不是容器元素上。

<transition-group>组件用于在多个元素插入或删除时添加过渡效果。例如,当我们在一个列表中添加或删除多个项目时,可以使用<transition-group>组件为这些操作添加一个动画效果。具体用法如下:

2.1. 基本用法

<template>
  <div>
    <button @click="handleAddLi">显示/隐藏</button>
    <transition-group tag="ul">
      <li v-for="item in items" :key="item.id">{
   
   { item.text }}</li>
    </transition-group>
  </div>
</template>

<script setup lang="ts">
import {
      
       reactive } from 'vue';

const items = reactive([
  {
      
      
    id: 1,
    text: 'test1'
  },
  {
      
      
    id: 2,
    text: 'test2'
  }
])

const handleAddLi = () => {
      
      
  items.push({
      
      
    id: items.length + 1,
    text: 'test' + (items.length + 1)
  })
}

</script>

<style scoped>
.v-enter-active,
.v-leave-active {
      
      
  transition: opacity 2s ease;
}

.v-enter-from,
.v-leave-to {
      
      
  opacity: 0;
}
</style>

在上面的代码中,我们使用<transition-group>组件将一个<ul>元素包裹起来,并使用v-for指令渲染一个列表。

猜你喜欢

转载自blog.csdn.net/to_the_Future/article/details/130297719