摘要:在现代 Web 应用中,流畅、美观的加载反馈能极大提升用户体验。Lottie 作为一种轻量级、高性能的矢量动画解决方案,已成为前端开发者的首选。本文将结合一个真实的 Vue3 + Element Plus 项目代码片段,深入剖析如何使用 lottie-web 库来集成和控制 JSON 格式的 Loading 动画,并详细解读其核心配置项与生命周期管理。

引言

你是否厌倦了千篇一律的 CSS 加载圈?是否希望为你的应用增添一丝丝精致的动态效果?Lottie 动画正是为此而生。它由 Airbnb 开源,允许设计师使用 After Effects 制作动画,并通过 Bodymovin 插件导出为体积小巧、可缩放且性能优异的 JSON 文件。前端开发者只需引入 lottie-web 库,即可轻松将这些动画嵌入网页。

本文将以一个典型的 AI 聊天界面为例,手把手教你如何在 Vue3 项目中实现一个“发送消息时显示 Loading 动画,收到响应后自动销毁”的完整流程。


1. 准备工作:安装与引入

首先,你需要在项目中安装 lottie-web

npm install lottie-web

然后,在你的 Vue 组件(如 index.vue)中引入它:

// index.vue
import lottie from "lottie-web";

同时,确保你已经从设计师或 LottieFiles 等平台获取了一个 .json 格式的动画文件,并将其放置在项目的 assets 目录下(例如 @/assets/img/loading.json)。


2. 核心实现:在 Vue3 中加载与控制 Lottie 动画

我们来看一下 index.vue 中处理发送消息和加载动画的核心逻辑。

2.1 创建动画容器

在模板 (<template>) 中,我们需要一个 div 作为 Lottie 动画的渲染容器。这里使用了 v-if 来根据 loading 状态决定是否显示。

<!-- index.vue (Template 部分) -->
<div class="answer" v-if="item.type === 'answer'">
  <!-- 加载状态显示动画 -->
  <div v-if="item.loading" class="loading-animation" id="loading-animation"></div>
  <!-- 加载完成显示内容 -->
  <div v-else class="markdown-body" v-html="item.content"></div>
</div>

关键点:

  • id="loading-animation": 这个唯一的 ID 是后续 JavaScript 获取 DOM 元素的关键。
  • class="loading-animation": 用于设置宽高样式。
2.2 在 nextTick 中初始化动画

<script setup>handleSend 方法中,当用户点击发送后,我们会向聊天列表中推入一条 loading: true 的消息。紧接着,利用 Vue 的 nextTick 确保 DOM 更新完成后再去操作这个新创建的容器元素。

// index.vue (Script 部分)
import { nextTick } from "vue";

const handleSend = async () => {
  // ... (省略前面的逻辑)

  // 发送消息后,检查是否需要自动滚动
  nextTick(() => {
    checkAutoScroll();
  });

  // 移除点阵动画定时器
  let loadingAnimation = null; 

  /** 
   * 使用Vue的nextTick确保在DOM更新完成后执行动画加载
   * 这是因为需要确保id为'loading-animation'的DOM元素已经渲染完成
   */
  nextTick(() => {
    const loadingContainer = document.getElementById('loading-animation');
    if (loadingContainer) {
      loadingAnimation = lottie.loadAnimation({
        container: loadingContainer, // 指定动画的容器元素
        renderer: 'svg',            // 设置渲染器类型为SVG(矢量图形,清晰度高)
        loop: true,                 // 设置动画循环播放
        autoplay: true,             // 设置动画自动播放
        path: new URL('@/assets/img/loading.json', import.meta.url).href // 动画JSON文件路径
      });
    }
  });

  // ... (省略后面的请求逻辑)
};

loadAnimation 配置项详解

这是 lottie-web 最核心的方法,其配置对象决定了动画的行为:

  • container: (必填) 一个 DOM 节点对象,Lottie 动画将被渲染到此容器内。
  • renderer: (必填) 渲染方式。常用值有:
    • 'svg' (推荐): 使用 SVG 渲染,矢量无损,清晰度高,适合大多数场景。
    • 'canvas': 使用 Canvas 渲染,性能极高,适合复杂或大量动画,但不支持 CSS 样式控制。
    • 'html': 使用 HTML/DOM 渲染,兼容性最好,但性能和功能最弱。
  • loop: (可选) 是否循环播放。可以是布尔值 true/false,也可以是数字指定循环次数。
  • autoplay: (可选) 是否在加载后自动开始播放。
  • path: (二选一) JSON 动画文件的 URL 路径。本例中使用 new URL(..., import.meta.url).href 是 Vite 构建工具下的最佳实践,能确保在开发和生产环境下都能正确解析静态资源路径。
  • animationData: (二选一) 如果你不想通过 path 加载,也可以直接将 JSON 对象作为数据传入。例如:animationData: require('@/assets/img/loading.json')
2.3 完美收尾:销毁动画实例

动画不能只开不关!否则会造成内存泄漏和不必要的性能消耗。在 index.vue 中,无论请求成功、失败还是被用户手动取消,都会调用 loadingAnimation.destroy() 来清理资源。

// index.vue (Script 部分 - handleSend 内)
try {
  await fetchStream(
    "/knowledge/api/knowledge/query",
    requestData,
    (chunk) => {
      // ... (处理流数据)
      
      // 当收到第一个有效数据块时,停止加载动画
      if (loadingAnswer.loading) {
        loadingAnswer.loading = false;
        if (loadingAnimation) {
          loadingAnimation.destroy(); // 👈 关键:销毁动画
          loadingAnimation = null;
        }
        // ... (重置其他状态)
      }
    },
    (error) => {
      // ... (错误处理)
      if (loadingAnimation) {
        loadingAnimation.destroy(); // 👈 错误时也要销毁
        loadingAnimation = null;
      }
    },
    () => {
      // ... (请求完成回调)
      if (loadingAnimation) {
        loadingAnimation.destroy(); // 👈 请求完成,最后确保销毁
        loadingAnimation = null;
      }
    },
    controller.signal
  );
} catch (error) {
  // ... (异常捕获)
  if (loadingAnimation) {
    loadingAnimation.destroy(); // 👈 异常时同样要销毁
    loadingAnimation = null;
  }
}

为什么 destroy() 如此重要?

  • 释放内存: 动画实例会持有对 DOM 元素和内部状态的引用,不销毁会导致内存无法被回收。
  • 停止计时器: Lottie 内部使用了 requestAnimationFrame 等机制,destroy() 会停止这些计时器,避免后台继续消耗 CPU 资源。
  • 清理 DOM: 它会移除所有由 Lottie 创建的子元素,保持 DOM 树的整洁。

3. 进阶技巧与注意事项
  • 动态路径处理: 在 Vite 或 Webpack 5+ 环境下,使用 new URL('...', import.meta.url).href 是处理静态资源路径的可靠方式,比传统的 require 或字符串拼接更健壮。
  • 动画控制: lottie.loadAnimation() 返回的实例 (loadingAnimation) 不仅可以 destroy(),还可以调用 play(), pause(), stop(), setSpeed(speed) 等方法进行精细控制。
  • 事件监听: 你可以监听动画的各种生命周期事件,如 complete, loopComplete, enterFrame 等,以实现更复杂的交互逻辑。
  • 性能考量: 虽然 Lottie 性能优秀,但仍应避免在同一页面上同时播放过多复杂动画。

总结

通过本文的分析,我们可以看到在 Vue3 项目中集成 Lottie 动画是一个既强大又简洁的过程。核心在于三点:

  1. 精准的 DOM 操作时机:利用 nextTick 确保在正确的时机操作 DOM。
  2. 合理的配置:根据需求选择合适的 renderer 和播放策略。
  3. 严格的生命周期管理:务必在组件卸载或动画不再需要时调用 destroy() 方法。

掌握这些要点,你就能轻松地为你的应用添加专业级的交互动画,让用户在等待的过程中也能感受到产品的用心与品质。快去试试吧!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐