Vue3 如何实现图片懒加载?其实一个 Intersection Observer 就搞定了

大家好,在当今图片密集的网络环境中,优化图片加载已成为前端开发的重要任务。今天我们分享一下怎么使用 Vue3 实现图片的懒加载功能。

什么是图片懒加载?

假如你打开一个有大量图片的页面,如果所有图片同时加载,会导致页面卡顿、流量浪费,特别是对于那些需要滚动才能看到的图片。

懒加载技术就是解决这个问题的方案,只有当图片进入或即将进入可视区域的时候,才加载它们

效果预览:

完整示例代码可在文末获取

实现原理

我们的Vue3懒加载实现基于以下核心技术:

1. Intersection Observer API

这是现代浏览器提供的强大API,可以高效监听元素是否进入可视区域,而无需频繁计算元素位置,性能远优于传统的滚动监听方式。

javascript 复制代码
// 创建观察器
observer.value = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) { // 元素进入可视区域
      loadImage();
      observer.value.unobserve(entry.target); // 加载后停止观察
    }
  });
}, {
  rootMargin: '50px 0px', // 提前50px开始加载
  threshold: 0.1 // 元素10%可见时触发
});

2. 组件化设计

我们将懒加载功能封装为独立的 LazyImage 组件,提高代码复用性和可维护性。

代码实现详解

组件模板结构

html 复制代码
<div class="lazy-image-container" ref="container">
  <img
    v-if="isLoaded && !hasError"
    :src="actualSrc"
    :alt="alt"
    class="lazy-image"
    :style="{ opacity: imageOpacity }"
    @load="onLoad"
    @error="onError"
  />
  <div v-else-if="hasError" class="image-placeholder">
    <div class="error-message">图片加载失败</div>
    <button @click="retryLoad" style="margin-top: 10px;">重试</button>
  </div>
  <div v-else class="image-placeholder">
    <div class="spinner"></div>
    <div>加载中...</div>
  </div>
</div>

组件包含三种状态:

  • 加载中:显示旋转加载动画
  • 加载完成:显示实际图片,带有淡入效果
  • 加载失败:显示错误信息和重试按钮

核心逻辑实现

状态管理

javascript 复制代码
setup(props, { emit }) {
  const isLoaded = ref(false);    // 是否已加载
  const hasError = ref(false);    // 是否加载失败
  const imageOpacity = ref(0);    // 图片透明度(用于淡入效果)
  const observer = ref(null);     // Intersection Observer实例
  const container = ref(null);    // 容器DOM引用
  const actualSrc = ref('');      // 实际图片地址
  // ...
}

使用Vue3的Composition API,我们可以更清晰地组织代码逻辑。

图片加载控制

javascript 复制代码
const loadImage = () => {
  if (props.slowLoad) {
    // 模拟慢速网络 - 延迟2秒加载
    setTimeout(() => {
      actualSrc.value = props.src;
      isLoaded.value = true;
    }, 2000);
  } else {
    // 正常加载
    actualSrc.value = props.src;
    isLoaded.value = true;
  }
};

这个函数根据slowLoad属性决定是否模拟慢速网络,便于测试不同网络条件下的表现。

生命周期管理

javascript 复制代码
onMounted(() => {
  // 创建并启动Intersection Observer
  observer.value = new IntersectionObserver((entries) => {
    // 观察逻辑...
  });
  
  if (container.value) {
    observer.value.observe(container.value);
  }
});

onUnmounted(() => {
  // 组件卸载时清理观察器
  if (observer.value) {
    observer.value.disconnect();
  }
});

确保在组件销毁时正确清理资源,避免内存泄漏。

错误处理与重试机制

javascript 复制代码
const onError = () => {
  hasError.value = true;
  emit('error'); // 向父组件发送错误事件
};

const retryLoad = () => {
  hasError.value = false;
  isLoaded.value = false;
  // 重新触发观察
  if (observer.value && container.value) {
    observer.value.observe(container.value);
  }
};

良好的错误处理机制可以提升用户体验,让用户在图片加载失败时有机会重试。

应用该组件

在主组件中使用懒加载

html 复制代码
<div class="gallery">
  <div 
    v-for="(image, index) in images" 
    :key="index" 
    class="image-card"
  >
    <lazy-image
      :src="image.url"
      :alt="image.title"
      :slow-load="networkSlow"
      @loaded="onImageLoaded"
      @error="onImageError"
    ></lazy-image>
    <div class="image-info">
      <div class="image-title">{{ image.title }}</div>
      <div class="image-description">{{ image.description }}</div>
    </div>
  </div>
</div>

功能控制与统计

我们的主组件提供了实用的控制功能:

  • 添加更多图片:动态加载更多图片
  • 重置图片:恢复初始状态
  • 模拟网络速度:切换正常/慢速网络模式
  • 加载统计:实时显示已加载和失败的图片数量

进一步优化

在实际项目中,还可以考虑以下优化:

  1. 图片压缩与格式选择:使用WebP等现代格式,减小文件体积
  2. 渐进式加载:先加载低质量预览图,再加载高清图
  3. 预加载关键图片:对首屏内的关键图片不使用懒加载
  4. 使用CDN加速:通过内容分发网络提高图片加载速度

Github示例代码github.com/1344160559-...

总结

Vue3图片懒加载是一个简单但极其实用的优化技术。通过Intersection Observer API和Vue3的响应式系统,我们可以以少量代码实现高效的懒加载功能,显著提升页面性能和用户体验。

这个实现不仅适用于图片展示类网站,也可以应用于任何需要优化资源加载的Vue3项目。希望本文能帮助你理解和实现这一重要前端优化技术!

本文首发于公众号:程序员刘大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!

📌往期精彩

《SpringBoot+MySQL+Vue实现文件共享系统》

《这20条SQL优化方案,让你的数据库查询速度提升10倍》

《SpringBoot 动态菜单权限系统设计的企业级解决方案》

《Vue3和Vue2的核心区别?很多开发者都没完全搞懂的10个细节》

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606112 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅13 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅13 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment13 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax