看下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;