详细讲一下Vue3中的Transition组件用法(动画)

1. 基础过渡动画

javascript 复制代码
<template>
  <!-- 
    transition 组件是 Vue 提供的内置组件
    name 属性定义了过渡类名的前缀
  -->
  <transition name="fade">
    <div v-if="show" class="box">Hello</div>
  </transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(false)
</script>

<style>
/* 进入和离开的过渡状态 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

/* 进入前和离开后的状态 */
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* 进入后和离开前的状态 */
.fade-enter-to,
.fade-leave-from {
  opacity: 1;
}
</style>

2. 自定义过渡类名

javascript 复制代码
<template>
  <!-- 
    使用自定义类名,可以配合第三方动画库使用
    比如 Animate.css
  -->
  <transition
    enter-active-class="animate__animated animate__fadeIn"
    leave-active-class="animate__animated animate__fadeOut"
  >
    <div v-if="show">自定义动画</div>
  </transition>
</template>

<script setup>
import 'animate.css'
import { ref } from 'vue'
const show = ref(false)
</script>

3. 过渡动画钩子

javascript 复制代码
<template>
  <transition
    @before-enter="onBeforeEnter"
    @enter="onEnter"
    @after-enter="onAfterEnter"
    @before-leave="onBeforeLeave"
    @leave="onLeave"
    @after-leave="onAfterLeave"
  >
    <div v-if="show" class="box">动画钩子</div>
  </transition>
</template>

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

// 进入过渡前
const onBeforeEnter = (el) => {
  el.style.opacity = 0
}

// 进入过渡中
const onEnter = (el, done) => {
  // 触发回流,使动画生效
  el.offsetHeight
  el.style.opacity = 1
  // 动画完成时调用 done
  done()
}

// 进入过渡后
const onAfterEnter = (el) => {
  console.log('进入完成')
}

// 离开过渡前
const onBeforeLeave = (el) => {
  el.style.opacity = 1
}

// 离开过渡中
const onLeave = (el, done) => {
  el.style.opacity = 0
  done()
}

// 离开过渡后
const onAfterLeave = (el) => {
  console.log('离开完成')
}
</script>

4. 列表过渡

javascript 复制代码
<template>
  <!-- 
    transition-group 用于列表过渡
    tag 指定渲染的元素
  -->
  <transition-group 
    name="list" 
    tag="ul"
  >
    <li 
      v-for="item in items" 
      :key="item.id"
      class="list-item"
    >
      {{ item.text }}
    </li>
  </transition-group>
</template>

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

const items = ref([
  { id: 1, text: '项目 1' },
  { id: 2, text: '项目 2' },
  { id: 3, text: '项目 3' }
])

// 添加项目
const addItem = () => {
  items.value.push({
    id: items.value.length + 1,
    text: `项目 ${items.value.length + 1}`
  })
}

// 删除项目
const removeItem = (index) => {
  items.value.splice(index, 1)
}
</script>

<style>
/* 列表项的基础样式 */
.list-item {
  display: inline-block;
  margin-right: 10px;
}

/* 进入和离开的过渡 */
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

/* 移动过渡 */
.list-move {
  transition: transform 0.5s ease;
}

/* 进入前和离开后的状态 */
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}
</style>

5. 状态过渡

javascript 复制代码
<template>
  <div>
    <!-- 数字动画 -->
    <div class="number">
      {{ animatedNumber }}
    </div>
    
    <!-- 颜色动画 -->
    <div 
      class="color-block"
      :style="{ backgroundColor: color }"
    ></div>
  </div>
</template>

<script setup>
import { ref, reactive, watch } from 'vue'
import gsap from 'gsap'

// 数字动画
const number = ref(0)
const animatedNumber = ref(0)

watch(number, (newValue) => {
  gsap.to(animatedNumber, {
    duration: 1,
    value: newValue
  })
})

// 颜色动画
const color = ref('#42b883')

const changeColor = () => {
  color.value = color.value === '#42b883' ? '#35495e' : '#42b883'
}
</script>

<style>
.color-block {
  width: 100px;
  height: 100px;
  transition: background-color 1s;
}
</style>

6. 可复用的过渡组件

javascript 复制代码
<!-- src/components/FadeTransition.vue -->
<template>
  <transition
    name="custom-fade"
    :duration="duration"
    v-bind="$attrs"
  >
    <slot></slot>
  </transition>
</template>

<script setup>
defineProps({
  duration: {
    type: [Number, Object],
    default: 300
  }
})
</script>

<style>
.custom-fade-enter-active,
.custom-fade-leave-active {
  transition: opacity 0.3s ease;
}

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

<!-- 使用方式 -->
<template>
  <FadeTransition :duration="500">
    <div v-if="show">内容</div>
  </FadeTransition>
</template>

7. 路由过渡

javascript 复制代码
<!-- App.vue -->
<template>
  <router-view v-slot="{ Component }">
    <transition 
      name="route" 
      mode="out-in"
    >
      <component :is="Component" />
    </transition>
  </router-view>
</template>

<style>
.route-enter-active,
.route-leave-active {
  transition: opacity 0.5s ease;
}

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

8. 组合动画示例

javascript 复制代码
<template>
  <div class="container">
    <transition
      name="modal"
      @before-enter="onBeforeEnter"
      @enter="onEnter"
      @leave="onLeave"
    >
      <div v-if="show" class="modal">
        <div class="modal-content">
          <h2>标题</h2>
          <p>内容</p>
          <button @click="show = false">关闭</button>
        </div>
      </div>
    </transition>
  </div>
</template>

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

const show = ref(false)

// 进入前
const onBeforeEnter = (el) => {
  el.style.opacity = 0
  const content = el.querySelector('.modal-content')
  content.style.transform = 'scale(0.8)'
}

// 进入中
const onEnter = (el, done) => {
  // 背景淡入
  gsap.to(el, {
    duration: 0.3,
    opacity: 1
  })
  
  // 内容缩放
  const content = el.querySelector('.modal-content')
  gsap.to(content, {
    duration: 0.3,
    scale: 1,
    onComplete: done
  })
}

// 离开
const onLeave = (el, done) => {
  // 背景淡出
  gsap.to(el, {
    duration: 0.3,
    opacity: 0
  })
  
  // 内容缩放
  const content = el.querySelector('.modal-content')
  gsap.to(content, {
    duration: 0.3,
    scale: 0.8,
    onComplete: done
  })
}
</script>

<style scoped>
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  transform-origin: center;
}
</style>

这些示例涵盖了 Vue3 中动画的主要使用场景。记住:

  • 使用 transition 组件处理单元素/组件过渡
  • 使用 transition-group 处理列表过渡
  • 可以使用 JavaScript 钩子实现复杂动画
  • 考虑使用第三方动画库增强效果
  • 注意性能优化和动画的适用场景
相关推荐
计算机-秋大田8 分钟前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
GDAL39 分钟前
HTML 中的 Canvas 样式设置全解
javascript
m0_528723811 小时前
HTML中,title和h1标签的区别是什么?
前端·html
Dark_programmer1 小时前
html - - - - - modal弹窗出现时,页面怎么能限制滚动
前端·html
GDAL1 小时前
HTML Canvas clip 深入全面讲解
前端·javascript·canvas
禾苗种树1 小时前
在 Vue 3 中使用 ECharts 制作多 Y 轴折线图时,若希望 **Y 轴颜色自动匹配折线颜色**且无需手动干预,可以通过以下步骤实现:
前端·vue.js·echarts
GISer_Jing1 小时前
Javascript排序算法(冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序)详解
javascript·算法·排序算法
贵州数擎科技有限公司1 小时前
使用 Three.js 实现流光特效
前端·webgl
JustHappy1 小时前
「我们一起做组件库🌻」做个面包屑🥖,Vue的依赖注入实战💉(VersakitUI开发实录)
前端·javascript·github
拉不动的猪2 小时前
刷刷题16
前端·javascript·面试