文章目录

Vue3的TransitionGroup与列表动画

发布于 2026-06-02 20:14:19 · 浏览 21 次 · 评论 0 条

Vue3的TransitionGroup与列表动画

在构建现代Web应用时,流畅、优雅的列表动画能极大提升用户体验。Vue3提供了专门的<TransitionGroup>组件来处理列表(如v-for渲染的项目)的增删和移动动画。本文将提供一份零基础、可立即上手的实战指南。


第一阶段:理解核心概念

<TransitionGroup> 是Vue内置的一个抽象组件,专门用于管理一组元素或组件(通常是列表)的进入、离开和移动过渡效果。它与普通的<Transition>组件不同,后者只管理单个元素的过渡。

它主要有三个核心作用:

  1. 为列表中的每个新元素应用进入动画
  2. 为列表中被移除的元素应用离开动画
  3. 为列表中位置发生变化的元素应用移动动画(通过FLIP技术实现平滑位移)。

核心属性

  • tag:指定<TransitionGroup>渲染为哪个HTML元素标签。默认是<span>,但通常我们会设为<ul><div>
  • name:自动生成的过渡类名前缀。例如,设置name="fade"后,Vue会自动应用.fade-enter-active.fade-leave-active等类名。
  • css:是否使用CSS过渡。默认为true。若想使用JavaScript动画钩子,可设为false
  • mode不适用于<TransitionGroup>。列表动画默认同时进行(先进后出)。

第二阶段:创建基础列表动画

本阶段将指导你创建一个带有淡入淡出移动效果的简单列表。

  1. 搭建基础模板。在你的Vue组件中,准备一个数组数据源和一个用于添加新项目的输入框。

    <template>
      <div>
        <input v-model="newItemText" @keyup.enter="addItem" placeholder="添加项目并回车" />
        <!-- 过渡容器 -->
        <TransitionGroup name="list" tag="ul">
          <li v-for="item in items" :key="item.id">
            {{ item.text }}
            <button @click="removeItem(item.id)">×</button>
          </li>
        </TransitionGroup>
      </div>
    </template>
  2. 编写对应的Script逻辑定义 items 数组和操作它的方法。

    <script setup>
    import { ref } from 'vue'
    
    const items = ref([
      { id: 1, text: '项目 A' },
      { id: 2, text: '项目 B' },
      { id: 3, text: '项目 C' }
    ])
    const newItemText = ref('')
    let nextId = 4
    
    const addItem = () => {
      if (newItemText.value.trim()) {
        items.value.push({
          id: nextId++,
          text: newItemText.value.trim()
        })
        newItemText.value = ''
      }
    }
    
    const removeItem = (id) => {
      const index = items.value.findIndex(item => item.id === id)
      if (index !== -1) {
        items.value.splice(index, 1)
      }
    }
    </script>
  3. 添加CSS过渡样式。这是实现动画的关键。创建以下CSS规则,定义从.list-开头的类名对应的样式。

    /* 进入动画的初始状态和离开动画的结束状态 */
    .list-enter-from,
    .list-leave-to {
      opacity: 0;
      transform: translateY(30px);
    }
    
    /* 进入动画的激活状态和离开动画的激活状态 */
    .list-enter-active,
    .list-leave-active {
      transition: all 0.5s ease;
    }
    
    /* 移动动画的过渡 */
    .list-move {
      transition: transform 0.5s ease;
    }

    关键点

    • .list-enter-from:定义了元素开始进入时的起始状态。
    • .list-enter-active:定义了元素进入过程中的过渡效果。
    • .list-leave-active:定义了元素离开过程中的过渡效果。
    • .list-leave-to:定义了元素离开结束时的最终状态。
    • .list-move:用于处理列表项位置变化的动画,Vue会自动应用FLIP技术。

第三阶段:实现交错动画效果

为了让列表更生动,可以让每个项目的动画依次延迟发生,形成交错效果。这通常通过JavaScript钩子或动态内联样式实现。

  1. 使用JavaScript钩子<TransitionGroup>提供了@before-enter@enter@leave等钩子。利用 @enter 钩子,可以动态设置每个元素的延迟。

    <TransitionGroup
      name="staggered-fade"
      tag="ul"
      @before-enter="onBeforeEnter"
      @enter="onEnter"
      @leave="onLeave"
    >
  2. 实现钩子函数编写以下JavaScript函数来控制动画延迟。这里使用了一个库(如velocity-animate)来执行动画,也可以使用纯CSS的transition-delay

    // 假设引入了动画库
    // import Velocity from 'velocity-animate'
    
    const onBeforeEnter = (el) => {
      el.style.opacity = 0
      el.style.height = 0
    }
    
    const onEnter = (el, done) => {
      // el.dataset.index 是我们在v-for中通过 :data-index="index" 传递的索引
      const delay = el.dataset.index * 150
      setTimeout(() => {
        // 使用动画库执行动画,完成后调用done
        Velocity(
          el,
          { opacity: 1, height: '1.6em' },
          { complete: done }
        )
      }, delay)
    }
    
    const onLeave = (el, done) => {
      const delay = el.dataset.index * 150
      setTimeout(() => {
        Velocity(
          el,
          { opacity: 0, height: 0 },
          { complete: done }
        )
      }, delay)
    }

    同时,修改 v-for 以传递索引::data-index="index"

  3. 纯CSS交错方案。如果不想使用JS库,定义一个基于transition-delay的CSS类,并通过内联样式动态设置--i变量。

    .staggered-fade-enter-active {
      transition: all 0.5s ease;
      transition-delay: calc(var(--i) * 100ms);
    }

    然后在模板中绑定样式::style="{'--i': index}"


第四阶段:结合状态与动画(实用技巧)

  1. 动画与响应式状态同步。Vue的响应式系统保证了items数组的变化会立即反映在DOM上,<TransitionGroup>则负责拦截这些变化并应用动画。因此,确保所有对items的修改都是通过其响应式代理方法(如push, splice)进行的。

  2. 处理初始列表渲染。默认情况下,列表初次渲染时项目没有进入动画。如果需要,添加 appear 属性。

    <TransitionGroup name="list" tag="ul" appear>
  3. 区分不同类型的动画。可以为进入和离开定义完全不同的动画效果。分别设置 .list-enter-active.list-leave-active 的样式。例如,进入时淡入并从左滑入,离开时淡出并向右滑出。

  4. 优化性能。对于长列表的移动动画,确保只为必要的CSS属性设置过渡。过多的属性(如transform, opacity以外的属性)会触发昂贵的重绘和回流。


最后一步:将上述代码整合到你的Vue单文件组件(.vue文件)中,运行项目,尝试添加和删除列表项,观察动画效果。通过调整.list-*类中的transition属性值(如持续时间duration、缓动函数timing-function),以及交错动画中的延迟计算,你可以打造出符合你应用风格的独特列表动画。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文