---
URL: "/zh-CN/blog/2025-09/vue-transition.html"
LLMS_URL: "/zh-CN/blog/2025-09/vue-transition.md"
lastUpdated: true
commentabled: true
recommended: true
title: "还在硬邦邦跳转页面？Vue这3招让应用丝滑如德芙！"
description: "还在硬邦邦跳转页面？Vue这3招让应用丝滑如德芙！"
date:

pageClass: "blog-page-class"
cover: "/covers/vue.svg"
---

---
lastUpdated: true
commentabled: true
recommended: true
title: 还在硬邦邦跳转页面？Vue这3招让应用丝滑如德芙！
description: 还在硬邦邦跳转页面？Vue这3招让应用丝滑如德芙！
date: 2025-09-19 15:30:00 
pageClass: blog-page-class
cover: /covers/vue.svg
---

你是不是也遇到过这种情况？页面切换生硬得像老式电视机换台，数据加载时用户一脸懵逼不知道发生了什么，列表操作毫无反馈让人怀疑到底点没点上...

别急！今天我就带你用Vue的过渡动画三招，让你的应用瞬间从"机械僵硬"变身"丝滑流畅"，用户体验直接提升一个level！

## 第一招：基础CSS过渡，简单又高效 ##

先来看看最基础的CSS过渡效果。Vue提供了 `<transition>` 组件，包裹一下就能让元素动起来！

```vue
<template>
  <div>
    <button @click="show = !show">切换显示</button>
    
    <transition name="fade">
      <p v-if="show">你好呀！我会淡入淡出哦~</p>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: true
    }
  }
}
</script>

<style>
/* 定义进入和离开时的动画 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s ease;
}

/* 定义进入开始和离开结束时的状态 */
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>
```

这里有个小秘密：Vue会自动帮我们在不同阶段添加不同的 class：

- `fade-enter`：进入动画开始前（第一帧）
- `fade-enter-active`：进入动画过程中
- `fade-enter-to`：进入动画结束后
- `fade-leave`：离开动画开始前
- `fade-leave-active`：离开动画过程中
- `fade-leave-to`：离开动画结束后

## 第二招：CSS动画，让效果更丰富 ##

如果觉得简单的过渡不够酷，试试CSS动画吧！用法和过渡差不多，但能做出更复杂的效果。

```vue
<template>
  <div>
    <button @click="show = !show">蹦出来！</button>
    
    <transition name="bounce">
      <p v-if="show" class="animated-text">看我弹跳登场！</p>
    </transition>
  </div>
</template>

<style>
/* 弹跳动画 */
.bounce-enter-active {
  animation: bounce-in 0.5s;
}

.bounce-leave-active {
  animation: bounce-in 0.5s reverse;
}

@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}

.animated-text {
  background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
  padding: 10px;
  border-radius: 5px;
  color: white;
}
</style>
```

这个效果特别适合重要提示或者操作反馈，让用户一眼就能注意到！

## 第三招：列表过渡，让数据动起来 ##

实际项目中我们经常要处理列表数据，`<transition-group>` 就是专门为列表设计的动画组件。

```vue
<template>
  <div>
    <button @click="addItem">添加项目</button>
    <button @click="removeItem">删除项目</button>
    
    <transition-group name="list" tag="ul">
      <li v-for="item in items" :key="item.id" class="list-item">
        {{ item.text }}
      </li>
    </transition-group>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, text: '第一项' },
        { id: 2, text: '第二项' },
        { id: 3, text: '第三项' }
      ],
      nextId: 4
    }
  },
  methods: {
    addItem() {
      this.items.push({
        id: this.nextId++,
        text: `新项目 ${this.nextId}`
      })
    },
    removeItem() {
      this.items.pop()
    }
  }
}
</script>

<style>
.list-item {
  transition: all 0.5s;
  margin: 5px 0;
  padding: 10px;
  background: #f8f9fa;
  border-left: 4px solid #4ecdc4;
}

.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}

.list-enter, .list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* 让删除的项目先收缩再消失 */
.list-leave-active {
  position: absolute;
}
</style>
```

注意这里有两个重点：一是必须给每个列表项设置唯一的 `key`，二是 `<transition-group>` 默认渲染为 `span`，可以用 `tag` 属性指定为其他标签。

## 进阶玩法：JavaScript钩子函数 ##

有时候CSS动画满足不了复杂需求，这时候就需要JavaScript钩子出场了！

```vue
<template>
  <div>
    <button @click="show = !show">切换</button>
    
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter"
      @enter-cancelled="enterCancelled"
      @before-leave="beforeLeave"
      @leave="leave"
      @after-leave="afterLeave"
      @leave-cancelled="leaveCancelled"
    >
      <div v-if="show" class="js-box">JS控制的动画</div>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: false
    }
  },
  methods: {
    // 进入动画开始前
    beforeEnter(el) {
      el.style.opacity = 0
      el.style.transform = 'scale(0)'
    },
    
    // 进入动画中
    enter(el, done) {
      // 使用requestAnimationFrame保证流畅性
      let start = null
      const duration = 600
      
      function animate(timestamp) {
        if (!start) start = timestamp
        const progress = timestamp - start
        
        // 计算当前进度（0-1）
        const percentage = Math.min(progress / duration, 1)
        
        // 应用动画效果
        el.style.opacity = percentage
        el.style.transform = `scale(${percentage})`
        
        if (progress < duration) {
          requestAnimationFrame(animate)
        } else {
          done() // 动画完成，调用done回调
        }
      }
      
      requestAnimationFrame(animate)
    },
    
    // 进入动画完成后
    afterEnter(el) {
      console.log('进入动画完成啦！')
    },
    
    // 进入动画被中断
    enterCancelled(el) {
      console.log('进入动画被取消了')
    },
    
    // 离开动画相关钩子...
    beforeLeave(el) {
      el.style.opacity = 1
      el.style.transform = 'scale(1)'
    },
    
    leave(el, done) {
      // 类似的实现离开动画...
      done()
    }
  }
}
</script>

<style>
.js-box {
  width: 100px;
  height: 100px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  margin-top: 10px;
}
</style>
```

JavaScript钩子虽然复杂一些，但是能实现任何你能想到的动画效果！

## 终极武器：集成第三方动画库 ##

如果你想快速实现酷炫效果，又不想自己写太多CSS，那么第三方动画库就是你的最佳选择！

先安装Animate.css：

```bash
npm install animate.css
```

然后在项目中引入：

```ts
import 'animate.css'
```

使用起来超级简单：

```vue
<template>
  <div>
    <button @click="show = !show">来点炫酷的！</button>
    
    <transition
      enter-active-class="animate__animated animate__bounceIn"
      leave-active-class="animate__animated animate__bounceOut"
    >
      <div v-if="show" class="demo-box">哇！好酷！</div>
    </transition>
  </div>
</template>

<style>
.demo-box {
  width: 150px;
  height: 150px;
  background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  margin-top: 20px;
  font-size: 18px;
  font-weight: bold;
}
</style>
```

Animate.css提供了超多现成动画效果，比如：

- `animate__bounceIn`（弹跳进入）
- `animate__fadeInUp`（淡入上浮）
- `animate__flip`（翻转效果）
- `animate__zoomIn`（缩放进入）

想要什么效果，换个class名就行了，简直是懒人福音！

## 实战技巧：避免这些常见坑 ##

用了这么久Vue动画，我也踩过不少坑，分享几个实用技巧：

- **动画闪烁问题**：在初始渲染时避免使用 `v-if`，可以用 `v-show` 或者通过CSS控制初始状态
- **列表动画优化**：对于长列表，可以给 `<transition-group>` 设置 `tag="div"`，避免生成太多DOM节点
- **性能注意**：尽量使用 `transform` 和 `opacity` 做动画，这两个属性不会触发重排，性能更好
- **移动端适配**：在移动端注意动画时长，`0.3s` 左右比较合适，不要太长
- **减少同时动画**：同一时间不要有太多元素做动画，会影响性能

## 总结 ##

好了，今天分享了Vue过渡动画的四大招式：从基础的CSS过渡，到更丰富的CSS动画，再到处理列表的 `<transition-group>`，最后是强大的JavaScript钩子和第三方库集成。

> 记住，好的动画不是为了炫技，而是为了提升用户体验。适当的动画能让用户知道发生了什么，引导注意力，让操作更有反馈感。
