前端图片渲染性能优化与实践 — 图片懒加载

前端图片渲染性能优化与实践 — 图片懒加载前言对于图片量比较大的点上首页 APP 等 在打开商品展示页面的时候需要再加大量图片 在这种场景下如果直接全量加载 必然会造成页面性能消耗过大 白屏或者卡顿 用户体验非常糟糕 用户真的需要我们显示所有图片一起展示吗 其实并不是 用户看到的只是浏览器可视区域的内容 所以从这个情况我们可以做一些优化 只显示用户可视区域内的图片 当用户触发滚动的瞬间再去请求显示给用户图片懒加载的实现 给所有需要展示的 img 标签添加自定义属性 data src 同时不要设置 src 属性 data src 的值为图片

前言

对于图片量比较大的点上首页APP等,在打开商品展示页面的时候需要再加大量图片,在这种场景下如果直接全量加载,必然会造成页面性能消耗过大,白屏或者卡顿,用户体验非常糟糕,用户真的需要我们显示所有图片一起展示吗?其实并不是,用户看到的只是浏览器可视区域的内容。所以从这个情况我们可以做一些优化,只显示用户可视区域内的图片,当用户触发滚动的瞬间再去请求显示给用户

图片懒加载的实现:

  1. 给所有需要展示的 img 标签添加自定义属性: data-src ,同时不要设置 src 属性,data-src的值为图片url。
  2. 当页面加载完后,我们需要获取所有需要懒加载的图片的元素集合,判断是否在可视区域,如果是在可视区域的话,再重新设置元素的src属性值为真正图片的地址。
  3. 可视化区域的判断:是通过获取元素的getBoundingClientRect属性的top值和页面的clientHeight进行对比,如果top值小于clientHeight,则说明元素出现在可视区域之内。
  4. 当用户滚动窗口的时候,此时应该通过每个元素的BoundingClientRect属性来判断元素是否出现在可视区域内,如果在可视区域内,就渲染图片展示在可是区域内。

懒加载的实现:

<!-- 只在可视化区域内加载图片 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> </body> <script> var viewHeight = document.documentElement.clientHeight; // 可视化区域的高度  var viewWidth = document.documentElement.clientWidth; // 可视化区域的宽度  function lazyload() { 
    //获取所有要进行懒加载的图片  let eles = document.querySelectorAll('img[data-src]'); // 获取属性名中有data-src的  console.log('获取所有的信息', eles) Array.prototype.forEach.call(eles, function (item, index) { 
    let rect; if (item.dataset.src === '') { 
    return; } rect = item.getBoundingClientRect(); // 返回元素的大小及其相对于视口的位置  console.log('返回元素的大小及其相对于视口的位置', rect) //图片一进入可视区,动态加载  if (rect.bottom >= 0 && rect.top < viewHeight) { 
    ! function () { 
    let img = new Image(); img.src = item.dataset.src; img.onload = function () { 
    item.src = img.src; } item.removeAttribute('data-src'); }(); } }) } lazyload(); </script> </html> 

上述代码中,我们已经初步完成图片懒加载,但是我们大家都知道,scroll这个事件,用户滚动鼠标就会触发很多次,这也会导致我们的性能急剧下降,所以这就引出了我们的混合体 防抖函数优化我们的性能:

function debounce(fn, gapTime) { 
    let timer = null; return function () { 
    if (timer) { 
    clearTimeout(timer); timer = null; } timer = setTimeout(function () { 
    fn(); }, gapTime) } } 

最后贴出完整代码:

<!-- 只在可视化区域内加载图片 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <img id="img" style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px;height: 250px;background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> </body> <script> var viewHeight = document.documentElement.clientHeight; // 可视化区域的高度 var viewWidth = document.documentElement.clientWidth; // 可视化区域的宽度 console.log('可视化区域的高度', viewHeight) console.log('可视化区域的宽度', viewWidth) let imgDom = document.getElementById('img'); console.log(window.getComputedStyle(imgDom, null).color); // 用来取所有的 function lazyload () { 
    //获取所有要进行懒加载的图片 let eles = document.querySelectorAll('img[data-src]'); // 获取属性名中有data-src的 console.log('获取所有的信息', eles) Array.prototype.forEach.call(eles, function(item, index) { 
    let rect; if(item.dataset.src === '') { 
    return; } rect = item.getBoundingClientRect(); // 返回元素的大小及其相对于视口的位置 console.log('返回元素的大小及其相对于视口的位置', rect) //图片一进入可视区,动态加载 if(rect.bottom >= 0 && rect.top < viewHeight) { 
    !function () { 
    let img = new Image(); img.src = item.dataset.src; img.onload = function () { 
    item.src = img.src; } item.removeAttribute('data-src'); }(); } }) } lazyload(); // 添加滚动事件触发图片加载 document.addEventListener('scroll', debounce(lazyload, 500), false); // 通过函数防抖来持续优化: function debounce(fn, gapTime) { 
    let timer = null; return function() { 
    if(timer) { 
    clearTimeout(timer); timer = null; } timer = setTimeout(function() { 
    fn(); }, gapTime) } } </script> </html> 

掘金链接:

  • https://juejin.cn/post/
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221135.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午6:50
下一篇 2026年3月17日 下午6:50


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号