您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

web前端图片加载的优化

时间:2021-09-06 13:03:45  来源:恒生LIGHT云社区  作者:麦乐

图像延迟加载

想要得到更好的性能体验,只靠资源压缩与恰当的文件格式选型,是很难满足期望的。我们还需要针对资源加载过程进行优化。

什么是延迟加载?

下图是京东商城的手机端首页,当元素没有滑动到视线内时,图片src属性放置了一个很小的图片,init_src属性放置了真正的图片,只要当该元素滑动到视线内部,才会将init_src属性赋值给src去加载真实的图片,这就是一个简单的图片延迟加载的过程。

web前端性能优化——图片加载的优化

 


web前端性能优化——图片加载的优化

 

传统方式延迟加载

就是事件监听的方式,通过监听scroll事件与resize事件,并在事件的回调函数中去判断,需要进行延迟加载的图片是否进入视窗区域。

我们只需要关注三个属性。

  • class属性,稍后会在JAVAScript中使用类选择器选取需要延迟加载处理的〈img〉标签。
  • src属性,加载前的占位符图片,可用Base64图片或低分辨率的图片。
  • data-src属性,通过该自定义属性保存图片真实的URL外链。
web前端性能优化——图片加载的优化

 

加入页面中有多张这样的图片需要加载。具体的JavaScript实现逻辑如下,在文档的DOMContentLoaded事件中,添加延迟加载处理逻辑,首先获取class属性名为lazy的所有〈img〉标签,将这些标签暂存在一个名为lazyImages的数组中,表示需要进行延迟加载但还未加载的图片集合。当一个图片被加载后,便将其从lazyImages数组中移除,直到lazyImages数组为空时,表示所有待延迟加载的图片均已经加载完成,此时便可将页面滚动事件移除。

这里使用了getBoundingClientRect()函数获取元素的相对位置.

        rectObject = object.getBoundingClientRect();

rectObject.top:元素上边到视窗上边的距离;

rectObject.right:元素右边到视窗左边的距离;

rectObject.bottom:元素下边到视窗上边的距离;

rectObject.left:元素左边到视窗左边的距离;

web前端性能优化——图片加载的优化

 

对于只可上下滚动的页面,判断一个图片元素是否出现在屏幕视窗中的方法其实显而易见,即当元素上边缘距屏幕视窗顶部的top值小于整个视窗的高度window.innerHeight时,预加载的事件处理代码如下:

document.addEventListener(DOMContentLoaded, function() {
      const imags = [].slice.call(document.querySelector('.lazy'))
      const active = false; // 限制函数被频繁调动
      function load() {
        if(active === false) {
          active = true
          setTimeout(() => {
            imags.forEach((img) => {
              const objPos = img.getBoundingClientRect();
              if(objPos.top <= window.innerHeight && objPos.bottom >=0 && img.display !== 'done') {
                img.src = img.dataset.src;
                img.classList.remove('lazy')
                imags.filter((i) => (i !== img))
                if(imags.length === 0) {
                  document.removeEventListener('scroll', load)
                  window.removeEventListener('resize', load)
                  window.removeEventListener('orientationchange', load)
                }
  
              }
            })
            active = false
          }, 200)
        }

      }

      document.addEventListener('scroll', load)
      window.addEventListener('resize', load)
      window.addEventListener('orientationchange', load)

    })

这种方式的有点就是兼容性比较好,缺点是频繁地进行计算必然会影响性能,代码也会比较繁琐。

实现图片的延迟加载:Intersection Observer方式

现代浏览器已大多支持了Intersection Observer API,用一句话简述:每当因页面滚动或窗口尺寸发生变化,使得目标元素(target)与设备视窗或其他指定元素产生交集时,便会触发通过Intersection Observer API配置的回调函数,在该回调函数中进行延迟加载的逻辑处理,会比传统方式显得更加简洁而高效。

简单来说,目标元素的可见性变化时,就会调用观察器的回调函数 callback。

callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。

 document.addEventListener(DOMContentLoaded, function() {
        const imags = [].slice.call(document.querySelector('.lazy'))
        if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
          var lazyImgObserver = new IntersectionObserver((entries, observer) => {
            entries.forEach((entry)=> {
              if(entry.isIntersecting) {
                var lazyImg = entry.target;
                lazyImg.src = lazyImg.dataset.src;
                lazyImg.classList.remove('lazy');
                lazyImgObserver.unobserve(lazyImg)
              }
            })
          })
          imags.forEach((img) => {
            lazyImgObserver.observe(img)
          })
        }
   
      })

这种方式判断元素是否出现在视窗中更为简单直观,应在实际开发中尽量使用,但其问题是并非所有浏览器都能兼容。

(1)做好尽量完备浏览器兼容性检查,对于兼容Intersection Observer API的浏览器,采用这种方式进行处理,而对于不兼容的浏览器,则切换回传统的实现方式进行处理。 (2)使用相应兼容的polyfill插件,在W3C官方GitHub账号下就有提供。

实现图片的延迟加载:css类名方式

这种实现方式通过CSS的background-image属性来加载图片,与判断〈img〉标签src属性是否有要请求图片的URL不同,CSS中图片加载的行为建立在浏览器对文档分析基础之上。

  document.addEventListener(DOMContentLoaded, function() {
        const imags = [].slice.call(document.querySelector('.lazy'))
        if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
          var lazyImgObserver = new IntersectionObserver((entries, observer) => {
            entries.forEach((entry)=> {
              if(entry.isIntersecting) {
                var lazyImg = entry.target;
                lazyImg.classList.add('visible');
                lazyImgObserver.unobserve(lazyImg)
              }
            })
          })
          imags.forEach((img) => {
            lazyImgObserver.observe(img)
          })
        }
   
      })
web前端性能优化——图片加载的优化

 

这种方式限制于需要提前写好css样式。

原生的延迟加载支持

除了上述通过开发者手动实现延迟加载逻辑的方式,从Chrome 75版本开始,已经可以通过〈img〉和〈iframe〉标签的loading属性原生支持延迟加载了,loading属性包含以下三种取值。

● lazy:进行延迟加载。 ● eager:立即加载。 ● auto:浏览器自行决定是否进行延迟加载。

测试:image标签就是 img

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- <script src="js/file2.js"></script> -->
  <!-- <script src="js/file3.js"></script> -->
  <!-- <link rel="stylesheet" href="css/index.css"> -->
  <style>
    img {
      width: 700px;
      height: 200px;
      display: block;
    }
  </style>
</head>
<body>

  
  
  <imgage loading="lazy" src='./image/home-1.png' alt="photo" />
  <imgage loading="lazy" src='./image/home-2.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-3.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-4.png' alt="photo" />
  <imgage loading="lazy" src='./image/home-5.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-6.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-7.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-8.png' alt="photo" />
  
  <imgage loading="lazy" src='./image/home-9.png' alt="photo" />
  <imgage loading="lazy" src='./image/home-10.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-11.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-12.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-13.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-14.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-15.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-16.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-17.png' alt="photo" />
  <imgage loading="lazy" src='./image/home-18.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-19.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-20.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-21.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-22.png' alt="photo" />
  
  <imgage loading="lazy" src='./image/home-23.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-24.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-25.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-26.png' alt="photo" />
  <imgage loading="lazy" src='./image/home-27.png' alt="photo" />

  <imgage loading="lazy" src='./image/home-28.png' alt="photo" />


  <imgage loading="lazy" src='./image/home-29.png' alt="photo" />

<imgage loading="lazy" src='./image/home-30.png' alt="photo" />



</body>
</html>
web前端性能优化——图片加载的优化

 

可以看到,首次加载的个数是13个,首屏一般只能放下4个左右,13个以后的img滚动到视线内部会自动去加载。

实践发现有以下几个特点:

  1. Lazy loading加载数量与屏幕高度有关,高度越小加载数量越少,但并不是线性关系。
  2. Lazy loading加载数量与网速有关,网速越慢,加载数量越多,但并不是线性关系。
  3. Lazy loading加载没有缓冲,滚动即会触发新的图片资源加载。
  4. Lazy loading加载在窗口resize尺寸变化时候也会触发,例如屏幕高度从小变大的时候。
  5. Lazy loading加载也有可能会先加载后面的图片资源,例如页面加载时滚动高度很高的时候。

与JavaScript有关的几个行为特征:

  1. 判断浏览器是否支持原生loading,最好使用'loading' in XXX判断。
  2. 获取loading属性值可以直接img.loading;
  3. 原生loading不可写,不可访问例如HTMLImageElement.prototype.loading会报错Illegal invocation。
  4. 如果要使用,注意做兼容性处理。


Tags:优化   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
此前有关厂商销售的显示器上,HDMI 2.1的标示问题闹得沸沸扬扬。按照官方的说法,HDMI 2.0标准已经不存在了,以后只有HDMI 2.1标准,后者的功能是可选的,显示器制造商只要具体说明该...【详细内容】
2021-12-24  Tags: 优化  点击:(8)  评论:(0)  加入收藏
对于一些文章页面来说,想要得到提升页面进行整体质量度,除了优化研究文章主体主要内容之外,调用相关分析文章也是企业优化的重点。那么我们具体怎么调用相关文章呢,星宇SEO今天...【详细内容】
2021-12-22  Tags: 优化  点击:(6)  评论:(0)  加入收藏
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,...【详细内容】
2021-12-08  Tags: 优化  点击:(23)  评论:(0)  加入收藏
App的性能优化,可以从多角度优化,包括App启动优化,App启动优化又分为main()函数执行前优化,main()函数执行后优化;包括界面卡顿优化,页面卡顿优化又包括CPU优化和GPU优化;包括安装包瘦...【详细内容】
2021-12-08  Tags: 优化  点击:(14)  评论:(0)  加入收藏
导读:网易大数据平台的底层数据查询引擎,选用了Impala作为OLAP查询引擎,不但支撑了网易大数据的交互式查询与自助分析,还为外部客户提供了商业化的产品与服务。今天将为大家分享...【详细内容】
2021-11-26  Tags: 优化  点击:(15)  评论:(0)  加入收藏
在我们使用win10操作系统的过程中,经常听到有小伙伴说win10系统没有win7系统好,win10会卡顿,今天小编来跟大家说说win10优化设置教程的介绍 - 装机吧的介绍,快来看看吧win10...【详细内容】
2021-11-22  Tags: 优化  点击:(40)  评论:(0)  加入收藏
最近发现B2B的海外推广貌似是一个挺大的缺口,很多厂长或老板不了解独立站的流量构成和玩法,无论是自然流量还是付费流量。也衍生了很多培训(咦,这是不是我副业的好机会?)所以这次...【详细内容】
2021-11-11  Tags: 优化  点击:(31)  评论:(0)  加入收藏
说明Web应用程序,MySQL数据库,数据库中有三张表:health_patient(病人表)、health_patient_account(病人账户表)、 health_patient_medical_history(病例表),视图需求是,页面分页展示病...【详细内容】
2021-11-05  Tags: 优化  点击:(32)  评论:(0)  加入收藏
摘要:如今越来越多的企业都在做网站优化,来增加品牌曝光率,从而获得客户实现销售。所以现在很多商家都会利用SEO优化做相应的营销和推广,从而引起更多的关注网站。企业做网站优...【详细内容】
2021-11-03  Tags: 优化  点击:(27)  评论:(0)  加入收藏
说起 WordPress 优化加速来可以说是个经久不衰的话题了,包括明月自己都撰写发表了不少相关的文章。基本上到现在为止明月的 WordPress 优化方案已经固定成型了,那就是 WP Supe...【详细内容】
2021-11-02  Tags: 优化  点击:(49)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条