JavaScript 懒加载全面总结

以下回答主要由 Deepseek AI 生成,经博主本人审核和增删整理,如有错漏请评论区反馈。

JavaScript 懒加载全面总结

懒加载基础概念

项目 描述 示例
定义 延迟加载资源的技术,只在需要时才加载 图片进入视口时再加载
核心思想 "按需加载",减少初始加载时间和资源消耗 不立即加载所有资源
对立概念 饥饿加载(Eager Loading) 页面加载时立即获取所有资源
适用场景 图片、视频、代码分割、第三方库等 非关键资源延迟加载

懒加载的实现原理

原理 技术手段 检测时机
视口检测 Intersection Observer API 元素进入可视区域时
滚动事件 监听 scroll 事件 + 位置计算 用户滚动时检查
手动触发 用户交互(点击、hover等) 特定动作发生时
条件加载 基于设备、网络等条件 满足特定条件时

不同类型的懒加载

图片懒加载

复制代码
// 使用 Intersection Observer(现代方式)
const lazyImages = document.querySelectorAll('img[data-src]');

const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            img.classList.remove('lazy');
            imageObserver.unobserve(img);
        }
    });
});

lazyImages.forEach(img => imageObserver.observe(img));

代码分割懒加载

复制代码
// 动态 import() - 组件懒加载
const LazyComponent = React.lazy(() => import('./ExpensiveComponent'));

// 路由懒加载
const routes = [
    {
        path: '/admin',
        component: () => import('./AdminPanel')
    }
];

第三方库懒加载

复制代码
// 按需加载第三方库
async function loadAnalytics() {
    if (userConsented) {
        const { Analytics } = await import('analytics-library');
        Analytics.track('page_view');
    }
}

懒加载的实现方式对比

实现方式 优点 缺点 适用场景
Intersection Observer 高性能,不阻塞主线程 兼容性需要处理 图片、广告等可视区域检测
Scroll 事件监听 兼容性好 性能较差,需要防抖 传统浏览器支持
动态 import() 原生支持,代码分割 需要构建工具配合 路由、组件懒加载
手动触发 完全控制加载时机 需要用户交互 模态框、复杂功能

图片懒加载详细实现

HTML 结构

复制代码
<!-- 懒加载图片 -->
<img 
    data-src="real-image.jpg" 
    src="placeholder.jpg" 
    alt="描述"
    class="lazy-image"
    loading="lazy"  <!-- 原生懒加载 -->
>

<!-- 懒加载背景图 -->
<div 
    class="lazy-bg"
    data-bg="background-image.jpg"
    style="background-image: url('placeholder.jpg')"
></div>

完整实现方案

复制代码
class LazyLoader {
    constructor() {
        this.images = [];
        this.init();
    }
    
    init() {
        if ('IntersectionObserver' in window) {
            this.initWithObserver();
        } else {
            this.initWithScroll();
        }
    }
    
    initWithObserver() {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    this.loadImage(entry.target);
                    observer.unobserve(entry.target);
                }
            });
        }, { rootMargin: '50px' }); // 提前50px加载
        
        document.querySelectorAll('[data-src], [data-bg]').forEach(el => {
            observer.observe(el);
        });
    }
    
    initWithScroll() {
        this.images = Array.from(document.querySelectorAll('[data-src], [data-bg]'));
        this.checkImages();
        
        // 防抖滚动监听
        const check = () => this.checkImages();
        window.addEventListener('scroll', check);
        window.addEventListener('resize', check);
    }
    
    checkImages() {
        this.images = this.images.filter(img => {
            if (this.isInViewport(img)) {
                this.loadImage(img);
                return false; // 从数组中移除
            }
            return true;
        });
        
        if (this.images.length === 0) {
            window.removeEventListener('scroll', this.checkImages);
        }
    }
    
    isInViewport(element) {
        const rect = element.getBoundingClientRect();
        return (
            rect.top <= window.innerHeight &&
            rect.bottom >= 0 &&
            rect.left <= window.innerWidth &&
            rect.right >= 0
        );
    }
    
    loadImage(element) {
        if (element.dataset.src) {
            element.src = element.dataset.src;
            element.removeAttribute('data-src');
        }
        if (element.dataset.bg) {
            element.style.backgroundImage = `url(${element.dataset.bg})`;
            element.removeAttribute('data-bg');
        }
    }
}

// 初始化
new LazyLoader();

性能优化策略

策略 实现方式 效果
预连接 <link rel="preconnect"> 提前建立连接
预加载关键资源 <link rel="preload"> 优先加载关键资源
懒加载非关键资源 上述懒加载技术 减少初始负载
响应式图片 srcset + sizes 按设备加载合适尺寸
渐进加载 低质量图片占位 → 高质量 更好的用户体验

浏览器原生懒加载

loading="lazy" 属性

复制代码
<!-- 原生图片懒加载 -->
<img 
    src="image.jpg" 
    loading="lazy" 
    alt="描述"
>

<!-- iframe 懒加载 -->
<iframe 
    src="content.html" 
    loading="lazy"
></iframe>

原生懒加载支持情况

浏览器 支持版本 备注
Chrome 76+ 全面支持
Firefox 75+ 支持
Safari 15.4+ 支持
Edge 79+ 基于 Chromium

最佳实践

实践 说明 理由
设置合适的阈值 提前 50-100px 开始加载 避免用户等待
提供占位符 使用低质量图片或纯色背景 保持布局稳定
错误处理 加载失败时显示备用内容 提升用户体验
性能监控 测量懒加载效果 持续优化
渐进增强 支持原生懒加载,降级到 JS 方案 兼容所有用户

懒加载的收益

指标 改善效果 测量方式
首次加载时间 减少 20-60% Lighthouse
首次内容绘制 显著提升 FCP 指标
页面重量 减少初始下载量 网络面板
用户体验 更快的可交互时间 用户反馈

懒加载是现代 Web 性能优化的核心技术之一,通过合理延迟非关键资源的加载,可以显著提升页面加载性能和用户体验。

相关推荐
Sheldon一蓑烟雨任平生24 天前
Vue3 异步组件(懒加载组件)
懒加载·vue3 异步组件·懒加载组件
cat10month1 个月前
react-loadable懒加载使用
懒加载
linweidong6 个月前
汇量科技前端面试题及参考答案
webpack·vue3·react·前端面试·hooks·懒加载·flex布局
Samdy_Chan8 个月前
同时支持Vue2/Vue3的图片懒加载组件(支持懒加载 v-html 指令梆定的 html 内容)
前端·vue·vue3·vue2·懒加载·图片懒加载·图像懒加载
大模型铲屎官10 个月前
【HTML性能优化】提升网站加载速度:GZIP、懒加载与资源合并
前端·性能优化·html·gzip·懒加载·网站加载·资源合并
GJWeigege1 年前
如何实现图片懒加载,原生 + React 实现方式
前端·react.js·前端框架·懒加载·图片懒加载优化·列表优化
Play_Sai1 年前
鸿蒙ArkTS实用开发技巧: 提高效率的关键知识点
网络请求·harmonyos·arkts·懒加载·钩子函数
会思想的苇草i1 年前
HTML深度探索 :img应用与实践
前端·html·图片·懒加载·预加载·img
Eveweiscsdn1 年前
视频懒加载
前端·javascript·react.js·视频·video·懒加载