什么是延迟加载?
延迟加载是一种性能优化技术,图像在进入(或即将进入)视口时加载。
延迟加载图像的用例
延迟加载在以下情况下特别有用:
- 图像库:显示大量图像时,延迟加载确保仅加载视图中的图像,从而防止加载时间过长并节省带宽。
- 长页面:在内容较多的页面上,延迟加载通过在用户滚动时加载图像来帮助缩短页面加载时间。
- 移动优化:对于使用较慢网络或移动设备的用户,延迟加载可确保他们只下载必要的内容,从而保留数据并改善浏览体验。
- 渐进式 Web 应用程序 (PWA): 延迟加载有助于提高 PWA 的性能。
编写标记
html
<div
id="gallery"
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
<!-- Images will be dynamically inserted here -->
</div>
编写 JavaScript
创建图像元素
我们将使用 createImageElement
函数动态创建图像元素。
js
const gallery = document.getElementById("gallery");
const imageUrls = [
"https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?q=80&w=1856&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1516914943479-89db7d9ae7f2?q=80&w=2732&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1531384698654-7f6e477ca221?q=80&w=2800&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1531901599143-df5010ab9438?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1524255684952-d7185b509571?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1588175996685-a40693ee1087?q=80&w=2864&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1624561172888-ac93c696e10c?q=80&w=2592&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1489424731084-a5d8b219a5bb?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
];
createImageElement
函数
此函数采用两个参数:图像的 URL 和数组中图像的索引。它返回一个包含图像的新 div
元素。
js
function createImageElement(url, index) {
const div = document.createElement("div");
div.className = "relative overflow-hidden aspect-w-16 aspect-h-9";
const img = document.createElement("img");
img.className =
"lazy-image w-full h-full object-cover transition-opacity duration-300 opacity-0";
img.dataset.src = url;
img.alt = `Image ${index + 1}`;
const placeholder = document.createElement("div");
placeholder.className = "absolute inset-0 bg-base-200 animate-pulse w-full h-full";
div.appendChild(placeholder);
div.appendChild(img);
return div;
}
lazyLoad 函数
该函数使用 IntersectionObserver API 来观察类为 lazy-image
的 img
元素。当类为 lazy-image
的元素与视口相交时,该元素的 src
属性会设置为 dataset.src
属性的值,并触发 onload
事件。
js
function lazyLoad() {
const images = document.querySelectorAll("img.lazy-image");
const options = {
root: null,
rootMargin: "0px",
threshold: 0.1,
};
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.onload = () => {
img.classList.remove("opacity-0");
img.previousElementSibling.remove(); // Remove placeholder
};
observer.unobserve(img);
}
});
}, options);
images.forEach((img) => imageObserver.observe(img));
}
创建和追加图像元素
我们将使用 createImageElement
函数创建图像元素并将其附加到库中。我们还将通过调用 lazyLoad
函数来初始化延迟加载。
js
// Create and append image elements
imageUrls.forEach((url, index) => {
const imageElement = createImageElement(url, index);
gallery.appendChild(imageElement);
});
// Initialize lazy loading
lazyLoad();
全部代码
js
const gallery = document.getElementById("gallery");
const imageUrls = [
"https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?q=80&w=1856&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1516914943479-89db7d9ae7f2?q=80&w=2732&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1531384698654-7f6e477ca221?q=80&w=2800&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1531901599143-df5010ab9438?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1524255684952-d7185b509571?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1588175996685-a40693ee1087?q=80&w=2864&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1624561172888-ac93c696e10c?q=80&w=2592&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1489424731084-a5d8b219a5bb?q=80&w=2787&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
];
function createImageElement(url, index) {
const div = document.createElement("div");
div.className = "relative overflow-hidden aspect-w-16 aspect-h-9";
const img = document.createElement("img");
img.className =
"lazy-image w-full h-full object-cover transition-opacity duration-300 opacity-0";
img.dataset.src = url;
img.alt = `Image ${index + 1}`;
const placeholder = document.createElement("div");
placeholder.className = "absolute inset-0 bg-base-200 animate-pulse w-full h-full";
div.appendChild(placeholder);
div.appendChild(img);
return div;
}
function lazyLoad() {
const images = document.querySelectorAll("img.lazy-image");
const options = {
root: null,
rootMargin: "0px",
threshold: 0.1,
};
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.onload = () => {
img.classList.remove("opacity-0");
img.previousElementSibling.remove(); // Remove placeholder
};
observer.unobserve(img);
}
});
}, options);
images.forEach((img) => imageObserver.observe(img));
}
// Create and append image elements
imageUrls.forEach((url, index) => {
const imageElement = createImageElement(url, index);
gallery.appendChild(imageElement);
});
// Initialize lazy loading
lazyLoad();