• 图片懒加载


    看下tuniu的页面,这有两个属性src和data-src

    一、第一次尝试

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8" />
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    6. <title>Lazy Load Images</title>
    7. <style>
    8. /* Placeholder style */
    9. .placeholder {
    10. width: 300px;
    11. height: 200px;
    12. background-color: #ccc;
    13. display: flex;
    14. justify-content: center;
    15. align-items: center;
    16. }
    17. </style>
    18. </head>
    19. <body>
    20. <!-- Placeholder for the image -->
    21. <div class="placeholder">Loading...</div>
    22. <div class="placeholder">Loading...</div>
    23. <div class="placeholder">Loading...</div>
    24. <div class="placeholder">Loading...</div>
    25. <div class="placeholder">Loading...</div>
    26. <div class="placeholder">Loading...</div>
    27. <div class="placeholder">Loading...</div>
    28. <div class="placeholder">Loading...</div>
    29. <div class="placeholder">Loading...</div>
    30. <div class="placeholder">Loading...</div>
    31. <div class="placeholder">Loading...</div>
    32. <div class="placeholder">Loading...</div>
    33. <div class="placeholder">Loading...</div>
    34. <div class="placeholder">Loading...</div>
    35. <div class="placeholder">Loading...</div>
    36. <div class="placeholder">Loading...</div>
    37. <div class="placeholder">Loading...</div>
    38. <div class="placeholder">Loading...</div>
    39. <div class="placeholder">Loading...</div>
    40. <div class="placeholder">Loading...</div>
    41. <div class="placeholder">Loading...</div>
    42. <div class="placeholder">Loading...</div>
    43. <div class="placeholder">Loading...</div>
    44. <div class="placeholder">Loading...</div>
    45. <!-- Actual image element with data-src attribute -->
    46. <img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" id="lazy-image" />
    47. <script>
    48. // Function to lazy load the image when it comes into the viewport
    49. function lazyLoadImage() {
    50. var lazyImage = document.getElementById("lazy-image");
    51. var scrollTop =
    52. window.pageYOffset ||
    53. (
    54. document.documentElement ||
    55. document.body.parentNode ||
    56. document.body
    57. ).scrollTop;
    58. var windowHeight = window.innerHeight;
    59. var imageOffsetTop = lazyImage.getBoundingClientRect().top + scrollTop;
    60. if (imageOffsetTop < windowHeight + scrollTop) {
    61. // Image is in the viewport, load the image
    62. lazyImage.src = lazyImage.getAttribute("data-src");
    63. // Remove the data-src attribute to prevent loading the image again
    64. lazyImage.removeAttribute("data-src");
    65. // Remove the event listener as the image is already loaded
    66. window.removeEventListener("scroll", lazyLoadImage);
    67. }
    68. }
    69. // Add event listener to lazy load the image when scrolling
    70. window.addEventListener("scroll", lazyLoadImage);
    71. // Initially trigger the lazy load function to check if the image is already in the viewport
    72. lazyLoadImage();
    73. </script>
    74. </body>
    75. </html>

    页面滚动到图片的位置才会加载相应的图片

    二、IntersectionObserver

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <title>IntersectionObserver 示例 - 图片懒加载</title>
    7. <style>
    8. .image-container {
    9. width: 300px;
    10. height: 200px;
    11. margin: 20px;
    12. border: 1px solid #ccc;
    13. display: flex;
    14. justify-content: center;
    15. align-items: center;
    16. }
    17. .image-container img {
    18. max-width: 100%;
    19. max-height: 100%;
    20. display: block;
    21. }
    22. .longBlock{
    23. height:1000px;
    24. width:1px;
    25. border:1px solid red;
    26. margin:10px;
    27. }
    28. </style>
    29. </head>
    30. <body>
    31. <div class="image-container">
    32. <img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
    33. </div>
    34. <div class="longBlock"></div>
    35. <div class="image-container">
    36. <img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
    37. </div>
    38. <div class="longBlock"></div>
    39. <div class="image-container">
    40. <img data-src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image">
    41. </div>
    42. <script>
    43. // 获取所有带有 data-src 属性的图片元素
    44. const lazyImages = document.querySelectorAll('img[data-src]');
    45. // 创建 IntersectionObserver 实例
    46. const observer = new IntersectionObserver((entries, observer) => {
    47. entries.forEach(entry => {
    48. // 当目标元素进入视窗时
    49. if (entry.isIntersecting) {
    50. const lazyImage = entry.target;
    51. lazyImage.src = lazyImage.dataset.src; // 加载图片
    52. observer.unobserve(lazyImage); // 停止观察该图片元素
    53. }
    54. });
    55. });
    56. // 遍历所有图片元素,开始观察
    57. lazyImages.forEach(image => {
    58. observer.observe(image);
    59. });
    60. </script>
    61. </body>
    62. </html>

    IntersectionObserver 是一个用于监视元素与其祖先元素或顶级文档视窗交叉状态的 API。这个 API 特别适用于实现无限滚动、延迟加载图片、懒加载和实现类似的场景。

    它的工作原理是观察一个或多个目标元素与其祖先元素或顶级文档视窗(viewport)的交叉状态。当目标元素进入或离开视窗或其祖先元素时,IntersectionObserver 会触发回调函数,从而允许开发者执行相应的操作。

    IntersectionObserver 提供了一种高效的方法来监视元素的可见性,而无需频繁地检查它们的位置或大小,这对于性能优化非常有用。它可以减少因为频繁的滚动事件监听而引起的性能问题,并且更容易实现各种基于元素可见性的功能。

    例如,你可以使用 IntersectionObserver 来实现以下功能:

    1. 无限滚动加载:当页面滚动到页面底部时,动态加载更多内容。
    2. 图片懒加载:只有当图片进入视窗时才加载图片资源,以节省带宽和加快页面加载速度。
    3. 广告展示:只有当广告元素进入用户视野时才加载广告内容,提高广告效果。
    4. 动画触发:当某个元素进入或离开视窗时触发动画效果。
    5. 网页性能优化:根据元素的可见性动态加载或卸载资源,以提高页面加载速度和性能。

    总之,IntersectionObserver 是一个非常有用的 Web API,它可以帮助开发者实现各种与元素可见性相关的功能,并且能够提高网页的性能和用户体验。

    三、react中:

    1. //LazyImage.jsx
    2. import React, { useState, useRef, useEffect } from 'react';
    3. const LazyImage = ({ src, alt }) => {
    4. const [isVisible, setIsVisible] = useState(false);
    5. const imageRef = useRef(null);
    6. useEffect(() => {
    7. const observer = new IntersectionObserver((entries) => {
    8. entries.forEach((entry) => {
    9. // 当目标元素进入视窗时
    10. if (entry.isIntersecting) {
    11. setIsVisible(true); // 设置图片可见
    12. observer.unobserve(entry.target); // 停止观察
    13. }
    14. });
    15. });
    16. if (imageRef.current) {
    17. observer.observe(imageRef.current); // 开始观察图片元素
    18. }
    19. return () => {
    20. if (imageRef.current) {
    21. observer.unobserve(imageRef.current); // 组件卸载时停止观察
    22. }
    23. };
    24. }, [src]); // 仅在 src 发生变化时重新运行 useEffect
    25. return (
    26. <img
    27. ref={imageRef}
    28. src={isVisible ? src : ''}
    29. alt={alt}
    30. />
    31. );
    32. };
    33. export default LazyImage;
    34. //App.jsx
    35. import React from 'react';
    36. import LazyImage from './LazyImage';
    37. const App = () => {
    38. return (
    39. <>
    40. <div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
    41. <LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
    42. <div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
    43. <LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
    44. <div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
    45. <LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
    46. <div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
    47. <LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
    48. <div style={{height:'1000px',width:'10px',border:'1px solid red'}}></div>
    49. <LazyImage src="https://img1.tuniucdn.com/site/images/yj_2016/init-img.jpg" alt="Lazy-loaded Image" />
    50. </>
    51. );
    52. };
    53. export default App;

  • 相关阅读:
    数字图像处理实验记录一(图像基本灰度变换)
    vue自定义密码输入框解决浏览器自动填充密码的问题
    JAVA集合04_Map接口概述、常用方法、排序、Hashtable面试题
    从保险科技看数字化如何改变保险行业
    四川竹哲电子商务有限公司培训服务引领你走向成功
    【改论文有感】给英语论文写作小白的有用提示!(二)文法章法篇
    计算机毕业设计Java小型超市商品信息管理(系统+源码+mysql数据库+lw文档)
    Casbin之Model模型存储(动态初始化)、Model模型存储(字符串加载)
    transient关键字使用说明
    面试官:Spring中都应用了哪些设计模式?
  • 原文地址:https://blog.csdn.net/m0_47999208/article/details/137925891