文档概述

本文基于原生 JavaScript IntersectionObserver API 实现的图片加载方案知识库说明,通过监听元素与视口的交叉状态,仅在图片进入视口时加载真实图片,减少初始页面加载资源消耗,提升页面性能与用户体验。

核心特性

  1. 原生 API 实现:基于 IntersectionObserver,无需引入第三方库,兼容性良好
  2. 性能优化:使用 DocumentFragment 批量操作 DOM,减少重绘重排
  3. 占位图策略:初始加载默认占位图,进入视口后替换为真实图片
  4. 自动停止观察:图片加载完成后自动取消观察,避免重复触发
  5. 视觉交互:包含卡片悬停缩放效果、自定义滚动条样式,提升用户体验

依赖说明

核心技术:原生 JavaScript(ES6+)、HTML5、CSS3

浏览器兼容性:支持 IntersectionObserver API 的现代浏览器(Chrome 51+、Firefox 55+、Safari 12.1+、Edge 79+)

外部资源:

  • 默认占位图:https://pica.zhimg.com/v2-f052aa50ca65df4bad1c3b7e4084d00e_1440w.jpg
  • 动态图片模板:https://picsum.photos/400/600?r={index}

完整代码实现

1. HTML 结构

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>JavaScript Observer 实现懒加载</title>
<link rel="stylesheet" href="https://www.jb51.net/javascript/css/index.css" rel="external nofollow"  />
</head>
<body>
<div class="card-list"></div>
<script src="https://www.jb51.net/javascript/js/index.js"></script>
</body>
</html>

2. CSS 样式

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: #f5f6f7;
}
.card-list {
--ap-gap: 16px;
--ap-min-width: 300px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--ap-min-width), 1fr));
gap: var(--ap-gap);
padding: 16px;
}
.card-list .item {
cursor: pointer;
height: 497px;
border-radius: 10px;
box-shadow: 0 0 6px #000;
overflow: hidden;
}
.card-list .item:hover img {
transform: scale(1.5);
}
.card-list .item img {
display: block;
width: 100%;
height: 100%;
transition: all 0.32s;
}
/* 自定义滚动条样式 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: #f5f5f5;
}
::-webkit-scrollbar-track-piece {
border-radius: 6px;
background-color: #f5f5f5;
}
::-webkit-scrollbar-thumb {
border-radius: 6px;
background-color: #ccc;
}
::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
::-webkit-scrollbar-thumb:active {
background-color: #787878;
}
::-webkit-scrollbar-corner {
background-color: #f5f5f5;
}
::-webkit-resizer {
background-repeat: no-repeat;
background-position: bottom right;
}

3. JavaScript 逻辑

// 配置项
const TOTAL_ITEMS = 99; // 总图片数量
const DEFAULT_IMG = 'https://pica.zhimg.com/v2-f052aa50ca65df4bad1c3b7e4084d00e_1440w.jpg'; // 默认占位图
const IMG_URL_TEMPLATE = (index) => `https://picsum.photos/400/600?r=${index}`; // 动态图片模板
const cardList = document.querySelector('.card-list');
/**
* 生成图片卡片
* 使用 DocumentFragment 批量操作 DOM,减少重绘重排
*/
function generateItems() {
const fragment = document.createDocumentFragment();
for (let i = 0; i < TOTAL_ITEMS; i++) {
const div = document.createElement('div');
div.classList.add('item');
const img = document.createElement('img');
img.src = DEFAULT_IMG; // 初始设置占位图
img.dataset.src = IMG_URL_TEMPLATE(i); // 真实图片地址存储在 data-src
img.alt = `Image ${i + 1}`;
div.appendChild(img);
fragment.appendChild(div);
}
cardList.appendChild(fragment); // 一次性插入所有元素
}
/**
* 初始化 Intersection Observer
* 监听图片与视口的交叉状态,实现懒加载
*/
function initLazyLoad() {
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return; // 跳过未进入视口的元素
const img = entry.target;
img.src = img.dataset.src; // 替换为真实图片
observer.unobserve(img); // 加载完成后停止观察
});
},
{
threshold: 0.01, // 交叉阈值:元素 1% 进入视口时触发
}
);
// 观察所有带有 data-src 属性的图片
document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img));
}
// 执行主逻辑
generateItems();
initLazyLoad();

核心实现说明

图片卡片生成

  • DocumentFragment 优化:使用文档片段暂存所有卡片元素,最后一次性插入 DOM,避免多次操作 DOM 导致的性能损耗
  • 占位图策略:初始 img.src 设置为默认占位图,真实图片地址存储在 data-src 自定义属性中
  • 动态图片地址:通过模板函数 IMG_URL_TEMPLATE 生成唯一的动态图片地址,避免缓存

Intersection Observer 初始化

  • 交叉阈值(threshold) :设置为 0.01,即图片 1% 进入视口时触发加载,提前加载提升流畅度
  • 回调处理:遍历所有观察项,仅处理进入视口的元素(entry.isIntersectingtrue
  • 自动停止观察:图片加载完成后调用 observer.unobserve(img),避免重复触发回调,节省性能

API 说明

IntersectionObserver 配置

配置项 类型 默认值 说明
threshold number 0 元素与视口的交叉比例阈值,达到该比例时触发回调
root Element null 观察的根元素,默认为视口
rootMargin string '0px' 根元素的外边距,用于提前或延迟触发

核心方法

方法名 说明
observe(target) 开始观察目标元素
unobserve(target) 停止观察目标元素
disconnect() 停止观察所有元素

使用示例

直接在浏览器中打开 HTML 文件即可体验:

  1. 页面初始加载 99 个带占位图的卡片
  2. 滚动页面,卡片进入视口时自动加载真实图片
  3. 鼠标悬停卡片,图片放大 1.5 倍
  4. 滚动条样式自定义,提升视觉体验

注意事项

  1. 浏览器兼容性IntersectionObserver 在 IE 及旧版本浏览器中不支持,如需兼容可引入 polyfill(如 intersection-observer
  2. 占位图优化:建议使用尺寸较小的占位图,减少初始加载资源
  3. 图片地址有效性:确保 data-src 存储的真实图片地址可访问
  4. 性能扩展:可结合 loading="lazy" 属性(原生懒加载)作为降级方案
  5. 错误处理:可添加图片加载失败的回调,替换为错误占位图
  6. 阈值调整:可根据实际需求调整 threshold 值,平衡加载时机与性能

到此这篇关于JavaScript实现图片懒加载的完整代码的文章就介绍到这了,更多相关JavaScript图片懒加载内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。