详细讲一下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 钩子实现复杂动画
  • 考虑使用第三方动画库增强效果
  • 注意性能优化和动画的适用场景
相关推荐
outstanding木槿1 小时前
react中实现拖拽排序
前端·javascript·react.js
ordinary902 小时前
vue.js scoped样式冲突
前端·vue.js
我要学编程(ಥ_ಥ)3 小时前
速通前端篇——JavaScript
开发语言·前端·javascript
大强的博客3 小时前
《Vue3实战教程》19:Vue3组件 v-model
前端·javascript·vue.js
塔塔开!.4 小时前
element ui 组件 时间选择器出现转换问题的解决办法
前端·javascript·vue.js
胡桃夹夹子5 小时前
前端,npm install安装依赖卡在sill idealTree buildDeps(设置淘宝依赖)
前端·npm·node.js
大叔_爱编程5 小时前
wx015基于springboot+vue+uniapp的经济新闻资讯的设计与实现
vue.js·spring boot·小程序·uni-app·毕业设计·源码·课程设计
xing.yu.CTF5 小时前
HTML基础到精通笔记
前端·笔记·html
Amo 67295 小时前
axios 实现进度监控
开发语言·前端·javascript
qq_419854056 小时前
js vue animation 数字动画
前端·javascript·vue.js