Hi FE !
Ai
git
前端面试题
前端小tip
  • vite
  • webpack
npm
  • vue2
  • vue3
react
GitHub
Ai
git
前端面试题
前端小tip
  • vite
  • webpack
npm
  • vue2
  • vue3
react
GitHub
  • 图片懒加载

图片懒加载

  1. 基本思路

初始渲染时不加载真实图片

把 img 标签的 src 换成一张占位图(小的 base64 或默认图片)

把真实地址存到自定义属性,比如 data-src

检测图片是否进入视口

当图片即将出现在视口(可视范围)时,替换 src 为真实图片地址

加载完成后可加渐隐动画(可选)

2. IntersectionObserver 实现(推荐)

<img data-src="https://example.com/real.jpg" alt="lazy" class="lazy" />
<img data-src="https://example.com/real2.jpg" alt="lazy" class="lazy" />

<script>
const imgs = document.querySelectorAll('img.lazy');

// 创建观察器
const observer = new IntersectionObserver((entries, obs) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src; // 替换为真实地址
      img.classList.remove('lazy');
      obs.unobserve(img); // 加载一次后取消监听
    }
  });
}, {
  root: null, // 视口
  threshold: 0.1 // 进入10%就触发
});

// 绑定观察器
imgs.forEach(img => observer.observe(img));
</script>

优点:

> 性能好(浏览器原生优化)

> 代码简洁

> 不用自己计算滚动位置

3. 滚动事件 + getBoundingClientRect 实现(兼容性好)


<img data-src="https://example.com/real.jpg" alt="lazy" class="lazy" />
<img data-src="https://example.com/real2.jpg" alt="lazy" class="lazy" />

<script>
function lazyLoad() {
  const imgs = document.querySelectorAll('img.lazy');
  const viewHeight = window.innerHeight;

  imgs.forEach(img => {
    const rect = img.getBoundingClientRect();
    if (rect.top < viewHeight && rect.bottom > 0) {
      img.src = img.dataset.src;
      img.classList.remove('lazy');
    }
  });
}

// 初始和滚动时调用
window.addEventListener('scroll', lazyLoad);
window.addEventListener('resize', lazyLoad);
lazyLoad();
</script>

缺点: 滚动时频繁触发,需要结合 throttle 防抖优化

手动计算元素位置

  1. 额外优化点 占位图:可用 1x1 base64 或 CSS 背景图 渐进式加载:先加载低清图,再替换高清图 提前加载:可以在进入视口前 100~200px 触发 SSR/SEO:如果是对搜索引擎友好的站点,要考虑服务端渲染补全图片
Edit this page
最近更新: 2025/12/2 01:46
Contributors: qdleader
qdleader
本站总访问量 129823次 | 本站访客数 12人