在 SPA 页面中,图片懒加载是一种非常常见的性能优化方法。由于 SPA 页面的内容是通过 Ajax 的方式进行加载的,因此在加载页面时一次性加载所有图片可能会影响网页的性能,特别是对于移动设备而言更是如此。而图片懒加载则可以在页面滚动到指定位置时再加载图片,从而减轻了页面的加载压力,提高了用户体验。
然而,在实际开发中,我们常常会遇到图片懒加载不起作用的问题。这篇文章将介绍在 SPA 页面开发中,如何解决图片懒加载不起作用的问题。
问题分析
在 SPA 页面中,图片懒加载通常是通过监听页面滚动事件(scroll
)实现的。当页面滚动到指定位置时,通过异步加载图片来实现懒加载效果。以下是一个简单的示例代码:
// javascriptcn.com 代码示例 <!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SPA 图片懒加载示例</title> <style> img { display: block; width: 100%; margin-bottom: 20px; } </style> </head> <body> <div id="list"> <!-- 图片列表 --> </div> <script> window.onload = function() { lazyLoad(); }; function lazyLoad() { var imgList = document.querySelectorAll('.lazy-load'); var length = imgList.length; var windowHeight = window.innerHeight; for (var i = 0; i < length; i++) { var img = imgList[i]; var rect = img.getBoundingClientRect(); if (rect.top < windowHeight) { var url = img.getAttribute('data-url'); img.src = url; img.removeAttribute('data-url'); img.classList.remove('lazy-load'); } } } window.addEventListener('scroll', lazyLoad); </script> </body> </html>
// javascriptcn.com 代码示例 // main.js var data = [ { url: 'https://picsum.photos/id/1001/600/400', alt: 'image 1' }, { url: 'https://picsum.photos/id/1002/600/400', alt: 'image 2' }, { url: 'https://picsum.photos/id/1003/600/400', alt: 'image 3' }, { url: 'https://picsum.photos/id/1004/600/400', alt: 'image 4' }, { url: 'https://picsum.photos/id/1005/600/400', alt: 'image 5' } ]; var html = ''; for (var i = 0; i < data.length; i++) { html += '<img class="lazy-load" data-url="' + data[i].url + '" alt="' + data[i].alt + '">'; } document.getElementById('list').innerHTML = html;
在上面的示例代码中,首先通过 main.js
生成了一组图片,然后在 index.html
中展示这组图片,并在图片标签上添加 lazy-load
类和 data-url
属性。图片的真实 URL 则通过 data-url
属性进行存储。当页面滚动时,通过 lazyLoad
函数遍历所有标记了 lazy-load
类的图片,判断是否已经滚动到了屏幕内,如果满足条件,则通过 data-url
属性获取真实 URL,并设置到 src
属性中进行加载。
常见问题分析
图片初始位置问题
在文章开始的示例代码中,使用 getBoundingClientRect
获取图片位置时,假设图片都在屏幕之外。这种情况下,由于 rect.top
值为负数,即使图片已被加载出来,也不会触发图片的懒加载。如果要解决这个问题,可以将 rect.top
判断的条件改为 rect.top < windowHeight && rect.top >= 0
,即假设图片都在屏幕内。
容器位置计算问题
在上文的示例代码中,假设容器的位置始终在文档底部。如果容器和页面的实际位置不符,那么也会出现图片懒加载不起作用的问题。为了解决这个问题,可以使用 offsetTop
属性获取容器距离文档顶部的距离,并用这个值来进行 rect.top
计算。
图片重复加载问题
如果使用上文的示例代码在列表中展示了多组图片,由于滚动事件会不断触发,存在多个图片同时满足加载条件。为了避免同一张图片被重复加载,可以在图片加载成功后,将 data-url
属性和 lazy-load
类移除,避免重复加载。
总结
在 SPA 页面开发中,图片懒加载是一种常见的性能优化方法。但是在实际开发中,由于容器位置和图片位置的计算问题,以及同时触发多张图片加载等问题,可能会导致图片懒加载不起作用。因此,在实际开发中,需要针对这些问题进行特定的优化,从而保证性能优化效果。
最后,为了方便大家阅读和学习,附上本文中使用的示例代码,感谢大家的阅读。
// javascriptcn.com 代码示例 <!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>SPA 图片懒加载示例</title> <style> img { display: block; width: 100%; margin-bottom: 20px; } </style> </head> <body> <div id="list"> <!-- 图片列表 --> </div> <script src="./main.js"></script> </body> </html>
// javascriptcn.com 代码示例 // main.js var data = [ { url: 'https://picsum.photos/id/1001/600/400', alt: 'image 1' }, { url: 'https://picsum.photos/id/1002/600/400', alt: 'image 2' }, { url: 'https://picsum.photos/id/1003/600/400', alt: 'image 3' }, { url: 'https://picsum.photos/id/1004/600/400', alt: 'image 4' }, { url: 'https://picsum.photos/id/1005/600/400', alt: 'image 5' } ]; var html = ''; for (var i = 0; i < data.length; i++) { html += '<img class="lazy-load" data-url="' + data[i].url + '" alt="' + data[i].alt + '">'; } document.getElementById('list').innerHTML = html; window.onload = function() { var imgList = document.querySelectorAll('.lazy-load'); var length = imgList.length; var windowHeight = window.innerHeight; var containerTop = document.getElementById('list').offsetTop; function lazyLoad() { for (var i = 0; i < length; i++) { var img = imgList[i]; var rect = img.getBoundingClientRect(); var imgTop = rect.top + containerTop; if (imgTop < windowHeight && imgTop >= 0) { var url = img.getAttribute('data-url'); img.src = url; img.removeAttribute('data-url'); img.classList.remove('lazy-load'); } } } lazyLoad(); window.addEventListener('scroll', lazyLoad); };
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654481e27d4982a6ebe5b2dc