You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中不使用任何库实现图片懒加载并优化图片引用?

当然可以手动搞定图片懒加载!其实像ng-defer-load、lazysizes这类库的核心逻辑并不复杂——就是判断图片什么时候进入用户的视口,再触发真实图片的加载。自己实现不仅能减少项目依赖、缩小包体积,还能完全掌控逻辑细节。下面我一步步教你优化你的图片代码:

手动实现图片懒加载的完整步骤

1. 改造现有img标签

首先,我们要把真实图片地址从src移到自定义属性里,同时给src设置一个轻量的占位图(避免初始请求无用资源)。保留width和height属性很重要,能防止图片加载后出现布局偏移。

你的原代码:

<img src="../../../assets/img/logo.png" width="100" height="100" style="display:inline-flex; float:left" />

改造后:

<img 
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" 
  data-src="../../../assets/img/logo.png" 
  width="100" 
  height="100" 
  style="display:inline-flex; float:left" 
  class="lazy-image"
/>

这里用了1x1的透明base64占位图,无需额外请求资源;加上lazy-image类方便后续通过JS选择元素。

2. 实现视口检测逻辑

核心是判断图片是否进入视口,这里有两种主流方案,推荐优先用第一种:

方案一:Intersection Observer API(现代浏览器首选)

这是浏览器原生支持的高性能API,由浏览器底层优化,不会像scroll事件那样频繁触发回调,性能更好。

// 获取所有需要懒加载的图片
const lazyImages = document.querySelectorAll('.lazy-image');

// 创建观察者实例
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    // 当图片进入视口时
    if (entry.isIntersecting) {
      const img = entry.target;
      // 把真实地址从data-src赋值给src
      img.src = img.dataset.src;
      // 加载完成后移除类并停止监听该图片
      img.classList.remove('lazy-image');
      observer.unobserve(img);
    }
  });
}, {
  // 可选配置:元素进入视口10%时触发加载
  threshold: 0.1
});

// 给每个懒加载图片添加监听
lazyImages.forEach(img => observer.observe(img));

方案二:Scroll事件监听(兼容旧浏览器)

如果需要兼容IE11这类不支持Intersection Observer的浏览器,可以用scroll事件结合getBoundingClientRect()来检测:

const lazyImages = document.querySelectorAll('.lazy-image');

function checkLazyImages() {
  lazyImages.forEach(img => {
    const rect = img.getBoundingClientRect();
    // 判断图片是否处于视口范围内
    const isInViewport = rect.top < window.innerHeight && rect.bottom > 0 &&
                         rect.left < window.innerWidth && rect.right > 0;
    // 仅当图片在视口且未加载时触发
    if (isInViewport && !img.src.includes('data:image')) {
      img.src = img.dataset.src;
      img.classList.remove('lazy-image');
    }
  });
}

// 页面初始化时先检查一次
checkLazyImages();

// 监听scroll事件,添加节流避免频繁触发
window.addEventListener('scroll', () => {
  clearTimeout(window.lazyLoadTimeout);
  window.lazyLoadTimeout = setTimeout(checkLazyImages, 200);
});

// 还要监听窗口 resize 和屏幕旋转事件,防止布局变化后漏检
window.addEventListener('resize', checkLazyImages);
window.addEventListener('orientationchange', checkLazyImages);

3. 额外优化细节

  • 添加加载状态样式:给懒加载图片加个加载动画,提升用户体验:
.lazy-image {
  background-color: #f5f5f5;
  background-image: linear-gradient(90deg, rgba(200,200,200,0) 0%, rgba(200,200,200,0.5) 50%, rgba(200,200,200,0) 100%);
  background-size: 200% 100%;
  animation: lazy-load-animation 1.5s infinite;
}

@keyframes lazy-load-animation {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
  • 区分首屏图片:首屏可见的图片不要加懒加载,直接保留原src,避免首屏内容延迟显示。
  • 响应式图片适配:如果需要支持不同屏幕尺寸,可以用data-srcset替代data-src,JS中赋值给srcset即可,逻辑和单图一致。

4. Angular框架适配(可选)

既然你提到了ng-defer-load,推测你用的是Angular。可以把懒加载逻辑封装成指令,在模板里使用更优雅:

import { Directive, ElementRef, OnInit, OnDestroy } from '@angular/core';

@Directive({
  selector: '[appLazyLoad]'
})
export class LazyLoadDirective implements OnInit, OnDestroy {
  private observer: IntersectionObserver | null = null;

  constructor(private el: ElementRef<HTMLImageElement>) {}

  ngOnInit(): void {
    const img = this.el.nativeElement;
    const realSrc = img.dataset.src;
    if (!realSrc) return;

    this.observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          img.src = realSrc;
          this.observer?.unobserve(img);
          this.observer = null;
        }
      });
    });

    this.observer.observe(img);
  }

  ngOnDestroy(): void {
    this.observer?.unobserve(this.el.nativeElement);
    this.observer?.disconnect();
  }
}

模板中使用:

<img 
  appLazyLoad
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" 
  data-src="../../../assets/img/logo.png" 
  width="100" 
  height="100" 
  style="display:inline-flex; float:left"
/>

内容的提问来源于stack exchange,提问作者user3408531

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:07:37