在Web应用开发中,图片资源往往是影响页面加载性能的关键因素,尤其是当页面包含大量图片或高清大图时,一次性加载所有图片会导致页面渲染缓慢、用户体验下降,Angular作为主流的前端框架,提供了多种实现图片懒加载的方案,其中结合JavaScript(JS)实现的懒加载技术因其灵活性和可控性,成为开发者的常用选择,本文将详细介绍Angular中基于JS的图片懒加载实现原理、核心代码逻辑、优化策略及注意事项。

懒加载的核心原理
图片懒加载的本质是延迟加载非首屏可见区域的图片,只有当图片即将进入用户视口(Viewport)时,才触发其加载,这一过程的核心在于监听滚动事件或使用Intersection Observer API判断图片元素与视口的相对位置,当图片进入视口后,动态将占位符或空图片(src属性设为空)替换为真实的图片地址(src属性),相比传统的<img>标签直接加载,懒加载能显著减少初始页面请求数量,降低带宽消耗和服务器压力。
基于Intersection Observer的实现方案
Intersection Observer是现代浏览器提供的原生API,用于异步监测目标元素与祖先元素或视口的交叉状态,相比传统滚动事件监听,它具有更高的性能和更低的资源消耗,以下是Angular中基于该API的懒加载实现步骤:
创建懒加载指令
在Angular中,可以通过自定义指令封装懒加载逻辑,首先使用@Directive装饰器定义一个指令,并在其中注入ElementRef和Renderer2服务来操作DOM元素,核心代码如下:

import { Directive, ElementRef, Renderer2, OnInit, OnDestroy } from '@angular/core';
@Directive({
selector: '[appLazyLoad]'
})
export class LazyLoadDirective implements OnInit, OnDestroy {
private observer: IntersectionObserver;
private imgElement: HTMLImageElement;
constructor(
private el: ElementRef,
private renderer: Renderer2
) {}
ngOnInit() {
this.imgElement = this.el.nativeElement;
// 设置初始占位图
this.renderer.setAttribute(this.imgElement, 'src', 'placeholder.jpg');
// 配置Intersection Observer
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadImage();
this.observer.unobserve(this.imgElement);
}
});
}, {
rootMargin: '50px' // 提前50px加载
});
this.observer.observe(this.imgElement);
}
private loadImage() {
const realSrc = this.imgElement.getAttribute('data-src');
if (realSrc) {
const img = new Image();
img.src = realSrc;
img.onload = () => {
this.renderer.setAttribute(this.imgElement, 'src', realSrc);
};
}
}
ngOnDestroy() {
this.observer?.disconnect();
}
}在模板中使用指令
在组件模板中,只需为需要懒加载的<img>标签添加appLazyLoad指令,并通过data-src属性存储真实图片地址:
<img appLazyLoad data-src="https://example.com/image.jpg" alt="Lazy loaded image" style="width: 100%; height: auto;" />
传统滚动事件监听的实现方案
对于需要兼容旧版浏览器的场景,可以通过监听滚动事件实现懒加载,虽然性能略逊于Intersection Observer,但通过节流(throttle)技术可以优化性能:
创建懒加载服务
import { Injectable } from '@angular/core';
import { fromEvent, Observable } from 'rxjs';
import { throttleTime, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class LazyLoadService {
private checkVisibility(): Observable<Element[]> {
return fromEvent(window, 'scroll').pipe(
throttleTime(200),
map(() => {
const images = document.querySelectorAll('img[data-src]');
return Array.from(images).filter(img => {
const rect = img.getBoundingClientRect();
return rect.top < window.innerHeight && rect.bottom > 0;
});
})
);
}
loadImages(images: Element[]) {
images.forEach(img => {
const imageElement = img as HTMLImageElement;
const src = imageElement.getAttribute('data-src');
if (src) {
imageElement.src = src;
imageElement.removeAttribute('data-src');
}
});
}
}在组件中调用服务
import { Component, OnInit, OnDestroy } from '@angular/core';
import { LazyLoadService } from './lazy-load.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-image-gallery',
template: `
<div *ngFor="let image of images">
<img [data-src]="image.url" alt="{{image.alt}}" />
</div>
`
})
export class ImageGalleryComponent implements OnInit, OnDestroy {
images = [
{ url: 'image1.jpg', alt: 'Image 1' },
{ url: 'image2.jpg', alt: 'Image 2' }
];
private subscription: Subscription;
constructor(private lazyLoadService: LazyLoadService) {}
ngOnInit() {
this.subscription = this.lazyLoadService.checkVisibility().subscribe(visibleImages => {
this.lazyLoadService.loadImages(visibleImages);
});
// 初始检查
this.lazyLoadService.loadImages(document.querySelectorAll('img[data-src]'));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}优化策略与注意事项
- 占位图处理:加载过程中可使用低质量图片占位符(LQIP)或纯色占位符,避免布局偏移(CLS)。
- 错误处理:为图片加载添加
onerror事件,加载失败时显示默认图片或提示信息。 - 预加载策略:对首屏图片或关键图片禁用懒加载,确保核心内容优先渲染。
- 性能对比:以下是两种实现方案的特性对比:
| 特性 | Intersection Observer | 滚动事件监听 |
|---|---|---|
| 性能 | 高(异步监听) | 中(需节流) |
| 兼容性 | 现代浏览器(IE不支持) | 全兼容 |
| 代码复杂度 | 低 | 中 |
| 支持交叉状态检测 | 是 | 否 |
- Angular内置优化:Angular的
NgOptimizedImage指令(v15+)提供了内置的图片懒加载和预加载功能,推荐在新项目中优先使用。
在Angular中实现图片懒加载,无论是基于Intersection Observer还是滚动事件监听,核心目标都是优化资源加载顺序,提升页面性能,Intersection Observer凭借其高效性和简洁性成为现代开发的首选,而滚动事件监听则在兼容性场景中发挥作用,开发者可根据项目需求选择合适的方案,并结合占位图、错误处理等优化手段,确保懒加载功能既高效又可靠,为用户提供流畅的浏览体验。

图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/29294.html




