看下tuniu的页面,这有两个属性src和data-src
一、第一次尝试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lazy Load Images</title>
<style>
/* Placeholder style */
.placeholder {
width: 300px;
height: 200px;
background-color: #ccc;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<!-- Placeholder for the image -->
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<div class="placeholder">Loading...</div>
<!-- Actual image element with data-src attribute -->
<img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" id="lazy-image" />
<script>
// Function to lazy load the image when it comes into the viewport
function lazyLoadImage() {
var lazyImage = document.getElementById("lazy-image");
var scrollTop =
window.pageYOffset ||
(
document.documentElement ||
document.body.parentNode ||
document.body
).scrollTop;
var windowHeight = window.innerHeight;
var imageOffsetTop = lazyImage.getBoundingClientRect().top + scrollTop;
if (imageOffsetTop < windowHeight + scrollTop) {
// Image is in the viewport, load the image
lazyImage.src = lazyImage.getAttribute("data-src");
// Remove the data-src attribute to prevent loading the image again
lazyImage.removeAttribute("data-src");
// Remove the event listener as the image is already loaded
window.removeEventListener("scroll", lazyLoadImage);
}
}
// Add event listener to lazy load the image when scrolling
window.addEventListener("scroll", lazyLoadImage);
// Initially trigger the lazy load function to check if the image is already in the viewport
lazyLoadImage();
</script>
</body>
</html>
页面滚动到图片的位置才会加载相应的图片
二、IntersectionObserver
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IntersectionObserver 示例 - 图片懒加载</title>
<style>
.image-container {
width: 300px;
height: 200px;
margin: 20px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
.image-container img {
max-width: 100%;
max-height: 100%;
display: block;
}
.longBlock{
height:1000px;
width:1px;
border:1px solid red;
margin:10px;
}
</style>
</head>
<body>
<div class="image-container">
<img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
</div>
<div class="longBlock"></div>
<div class="image-container">
<img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
</div>
<div class="longBlock"></div>
<div class="image-container">
<img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
</div>
<script>
// 获取所有带有 data-src 属性的图片元素
const lazyImages = document.querySelectorAll('img[data-src]');
// 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
// 当目标元素进入视窗时
if (entry.isIntersecting) {
const lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src; // 加载图片
observer.unobserve(lazyImage); // 停止观察该图片元素
}
});
});
// 遍历所有图片元素,开始观察
lazyImages.forEach(image => {
observer.observe(image);
});
</script>
</body>
</html>
IntersectionObserver 是一个用于监视元素与其祖先元素或顶级文档视窗交叉状态的 API。这个 API 特别适用于实现无限滚动、延迟加载图片、懒加载和实现类似的场景。
它的工作原理是观察一个或多个目标元素与其祖先元素或顶级文档视窗(viewport)的交叉状态。当目标元素进入或离开视窗或其祖先元素时,IntersectionObserver 会触发回调函数,从而允许开发者执行相应的操作。
IntersectionObserver 提供了一种高效的方法来监视元素的可见性,而无需频繁地检查它们的位置或大小,这对于性能优化非常有用。它可以减少因为频繁的滚动事件监听而引起的性能问题,并且更容易实现各种基于元素可见性的功能。
例如,你可以使用 IntersectionObserver 来实现以下功能:
- 无限滚动加载:当页面滚动到页面底部时,动态加载更多内容。
- 图片懒加载:只有当图片进入视窗时才加载图片资源,以节省带宽和加快页面加载速度。
- 广告展示:只有当广告元素进入用户视野时才加载广告内容,提高广告效果。
- 动画触发:当某个元素进入或离开视窗时触发动画效果。
- 网页性能优化:根据元素的可见性动态加载或卸载资源,以提高页面加载速度和性能。
总之,IntersectionObserver 是一个非常有用的 Web API,它可以帮助开发者实现各种与元素可见性相关的功能,并且能够提高网页的性能和用户体验。
三、react中:
//LazyImage.jsx
import React, { useState, useRef, useEffect } from 'react';
const LazyImage = ({ src, alt }) => {
const [isVisible, setIsVisible] = useState(false);
const imageRef = useRef(null);
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
// 当目标元素进入视窗时
if (entry.isIntersecting) {
setIsVisible(true); // 设置图片可见
observer.unobserve(entry.target); // 停止观察
}
});
});
if (imageRef.current) {
observer.observe(imageRef.current); // 开始观察图片元素
}
return () => {
if (imageRef.current) {
observer.unobserve(imageRef.current); // 组件卸载时停止观察
}
};
}, [src]); // 仅在 src 发生变化时重新运行 useEffect
return (
<img
ref={imageRef}
src={isVisible ? src : ''}
alt={alt}
/>
);
};
export default LazyImage;
//App.jsx
import React from 'react';
import LazyImage from './LazyImage';
const App = () => {
return (
<>
<div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
<LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
<div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
<LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
<div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
<LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
<div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
<LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
<div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
<LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
</>
);
};
export default App;