前端必会的图片懒加载,你造吗?

一.何为懒加载🌃:

  在我们访问一个图片展示比较多的网页时,加载速度慢很多时候正是因为图片多导致,大量的img图片导致页面渲染的堵塞。当费了许多力气把全部图片和页面加载出来时而用户早已离去。另一方面,若用户只查看了网页的前面部分便离开,许多已经加载却因为处于网页底部而未呈现在视口区的图片,它们极大加重服务器压力了但是用户看都没看,白白浪费了性能。
  为了解决上面的问题需要引入图片懒加载,懒加载其实很好理解,重点就是一个‘懒’字。当用户滚动相应可视区域,若可视区域有图片便加载,而在可视区域外未加载过的图片它们先不加载,如果用户滚动可视区域到它们时它们再加载,否则一律不加载。这样一来就大大提高了网页渲染的性能和减少不必要的浪费。

二.实现懒加载🌄:

  首先,先定义一个基本的HTML页面模拟一些存在大量图片的网页,比如我用8个img 标签来模拟,同时定义一些基本css样式,代码与初始效果如下:

html:

    <img src="img/1.jpg" alt="xxx" />
    <img src="img/2.jpg" alt="xxx" />
    <img src="img/3.jpg" alt="xxx" />
    <img src="img/4.jpg" alt="xxx" />
    <img src="img/5.jpg" alt="xxx" />
    <img src="img/6.jpg" alt="xxx" />
    <img src="img/7.jpg" alt="xxx" />
    <img src="img/8.jpg" alt="xxx" />

css:

 * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      img {
        width: 500px;
        height: 300px;
        object-fit: cover;
        margin: 20px;
      }
      body {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-evenly;
      }

初始效果如下,可以看到右边的控制台,8张图片在我一运行这个页面的时候就都一同被加载渲染了:

在这里插入图片描述
  下面是利用JavaScript实现懒加载的3种方式,原理都是判断图片是否出现在可视区后给图片赋值src属性。

2.1 第一种方式:

  首先,修改每一个img标签,利用HTML提供的 data- 属性来嵌入自定义数据,这个自定义数据我们存放这个标签原本的图片地址。同时,全部的图片的src属性我们都用一张同样的图表示,这个图一般可为显示载入中字样的图片。注意,如果多个img标签src引用的是同一张图片,那么只会加载一次,不会多次加载,所以我下面给每个图src定义同一张图。

    <img data-src="img/1.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/2.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/3.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/4.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/5.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/6.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/7.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/8.jpg" src="img/0.png" alt="xxx" />

此时页面效果如下,:

在这里插入图片描述
  接下来用JavaScript实现当我们滚动滚动条时,如果图片出现在可视区,那么加载图片。加载图片其实就是给img标签src属性赋值为本来的地址,那么此时图片便会请求加载渲染出来。

 //获取全部img标签
var images = document.getElementsByTagName("img");

 window.addEventListener("scroll", (e) => {
    //当发生滚动事件时调用ergodic事件
    ergodic();
  });
  function ergodic() {
    // 遍历每一张图
    for (let i of images) {
      //判断当前图片是否在可视区内
      if (i.offsetTop <= window.innerHeight + window.scrollY) {
          //获取自定义data-src属性的值
          let trueSrc = i.getAttribute("data-src");
          //把值赋值给图片的src属性
          i.setAttribute("src", trueSrc);
      }
    }
  }
  //没发生滚动事件时也要先执行一次
  ergodic();

 其中, offsetTop 为元素距离顶部的距离;window.innerHeight 为当前窗口的高度;window.scrollY 为滚动距离;不难知道,当 i.offsetTop <= window.innerHeight + window.scrollY时图片就处于窗口可视区了。

此时效果如下,观察右侧控制台,发现当滚动时图片才加载:

在这里插入图片描述

2.2 第二种方式:

第二种方式其实和第一种差不多,只是计算图片是否在可视区方式不同,重复的部分就省略了,如下:

  window.addEventListener("scroll", (e) => {
        ergodic();
      });
      function ergodic() {
        for (let i of images) {
          //计算方式和第一种方式不同
          if (i.getBoundingClientRect().top < window.innerHeight) {
            let trueSrc = i.getAttribute("data-src");
            i.setAttribute("src", trueSrc);
          }
        }
      }
      ergodic();

 其中,getBoundingClientRect().top 为元素相对于窗口的位置;window.innerHeight 为当前窗口的高度;当元素对于窗口的位置小于当前窗口的高度时,那自然处于了窗口可视区了。

效果一样的:

在这里插入图片描述

2.3 第三种方式(优):

 其实上面两种方式已经大致实现懒加载,但是,它们都有一个缺点,就是一当发生滚动事件时,就发生了大量的循环和判断操作判断图片是否可视区里。这自然是不太好的,那是否有解决方法。这里就引入了一个叫 Intersection Observer 观察器接口,它是是浏览器原生提供的构造函数,使用它能省到大量的循环和判断。当然它的兼容可能不太好,看情况使用。

 Intersection Observer 是什么呢?这个构造函数的作用是它能够观察可视窗口与目标元素产生的交叉区域。简单来说就是当用它观察我们的图片时,当图片出现或者消失在可视窗口,它都能知道并且会执行一个特殊的回调函数,我们就利用这个回调函数实现我们的操作。概念枯燥难懂,直接看下面例子:

1.既然IntersectionObserver是浏览器原生提供的构造函数,先new一个实例:

 const observer = new IntersectionObserver(callback);

 其中它会有一个参数callback,参数为一个回调函数,当目标元素能看见会触发一次,目标元素看不见会再触发一次。

2.使用实例通过observer属性可以为每一张图片绑定一个观察器:

  for (let i of images) {
        observer.observe(i);
      }

3.由上可以知道每张图片能看见会和看不见时都会触发一次callback回调函数,同时callback这个回调函数也有一个参数entries,我们可以运行触发这个回调函数看看它是什么:

 function callback(entries) {
      console.log(entries)
      }

在这里插入图片描述

 可以看到每次图片能看见会和看不见时都会触发一次callback回调函数,并输出了参数entries的内容。其实,entries为一个数组,而它的数组元素为当前改变了状态触发了事件的目标元素。其中有一个isIntersecting属性,当目标元素在视口看得见为它true,不在时它为 false 。我们就可以利用这个属性,当它为 true 时设置触发这个事件的图片的src属性值为data-src,开始加载。

function callback(entries) {
        for (let i of entries) {
          if (i.isIntersecting) {
              let img = i.target;
              let trueSrc = img.getAttribute("data-src");
              img.setAttribute("src", trueSrc);
          }
        } 
      }

 其中 target 事件属性返回触发事件的元素。当前,当回来滚动时,图片会一会可见一会不可见,它都是触发回调函数,所以当某图片已经加载时我们要停掉它的观察器。利用unobserve属性可停掉。

  function callback(entries) {
    for (let i of entries) {
      if (i.isIntersecting) {
          let img = i.target;
          let trueSrc = img.getAttribute("data-src");
          img.setAttribute("src", trueSrc);
          // 结束观察
          observer.unobserve(img);
      }
    } 
  }

完整代码:

 var images = document.getElementsByTagName("img");
   function callback(entries) {
    for (let i of entries) {
      if (i.isIntersecting) {
          let img = i.target;
          let trueSrc = img.getAttribute("data-src");
          img.setAttribute("src", trueSrc);
          observer.unobserve(img);
      }
    } 
  }
      const observer = new IntersectionObserver(callback);
      for (let i of images) {
        observer.observe(i);
      }

效果如下,实现懒加载:

在这里插入图片描述

三.总结🌇:

  以上就为实现图片懒加载的全部内容啦。✨总的来说就是某些存在大量的img的网页如果页面渲染阶段就把图片全部加载,那会导致页面渲染的堵塞。为了解决引入图片懒加载,用户滚动相应可视区域,若可视区域有图片那么该图片才加载。其中核心就是给图片定义自定义属性data-src存放图片真的访问地址,当图片出现在可视区时才将data-src的值赋值给src属性,此时图片便加载。其中不止不可通过一些常见属性判断图片位置,还引入了IntersectionObserver观察器接口更少消耗的实现懒加载。如果文中有错误的地方,恳请大佬指出。✨

  下次见啦~ 晚安好梦 (¦3[▓▓] ⭐⭐⭐🌙

在这里插入图片描述
其它文章:
~关注我看更多简单创意特效:
文字烟雾效果 html+css+js
环绕倒影加载特效 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等等
进我主页看更多~

  • 22
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
1、 JavaScript 的基本类型有哪些?引用类型有哪些?null 和 undefined 的区别?(必 会) 76 2、如何判断 JavaScript 的数据类型?(必会JavaScript 数据类型一共有 7 种: 77 2、 创建对象有几种方法(必会) 79 4、简述创建函数的几种方式? (必会) 79 5、Javascript 创建对象的几种方式? (必会) 79 6、请指出 JavaScript 宿主对象和原生对象的区别?(必会) 81 7、 JavaScript 内置的常用对象有哪些?并列举该对象常用的方法?(必会) 82 8、 === 和 ==的区别?(必会) 87 9、 null,undefined 的区别(必会) 88 10、JavaScript 中什么情况下会返回 undefined 值?(必会) 88 11、如何区分数组和对象?(必会) 89 12、怎么判断两个对象相等?(必会) 89 13、列举三种强制类型转换和两种隐式类型转换?(必会) 91 14、 JavaScript 中怎么获取当前日期的月份?(必会) 91 15、 什么是类数组(伪数组),如何将其转化为真实的数组?(必会) 92 16、如何遍历对象的属性?(必会) 92 17、src 和 href 的区别是?(必会) 94 18、如何使用原生 JavaScript 给一个按钮绑定两个 onclick 事件?(必会) 95 19、 如何在 JavaScript 中比较两个对象?(必会) 95 20、JavaScript 中的作用域、预解析与变量声明提升? (必会) 97 21、变量提升与函数提升的区别?(必会) 99 22、 什么是作用域链?(必会) 99 23、如何延长作用域链?(必会) 99 23、 判断一个值是什么类型有哪些方法?(必会) 100 25、JavaScript 变量按照存储方式区分为哪些类型,并描述其特点?(必会) 100 26、如何实现数组的随机排序?(必会) 100 27、 Function foo() {}和 var foo = function() {}之间 foo 的用法上的区别?(必会) 101 28、索引有哪几种类型,有什么区别?(了解) 102 29、简述 Array.form 和 Array.of 的使用及区别?(了解) 103 30、根据你的理解,请简述 JavaScript 脚本的执行原理(了解) 104 WebAPI 105 1、 什么是 dom?(必会) 105 2、dom 是哪种基本的数据结构?(必会) 105 3、 dom 操作的常用 api 有哪些?(必会) 105 4、 dom 节点的 Attribute 和 Property 有何区别?(必会) 106 5、dom 结构操作怎样添加、移除、移动、复制、创建和查找节点?(必会) 106 6、dom 事件的级别?(必会) 107 7、dom 事件模型?(必会) 107 8、dom 事件流?(必会) 107 9、什么是事件冒泡,它是如何工作的?如何阻止事件冒泡?(必会) 108 10、JavaScript 动画和 CSS3 动画有什么区别?(必会) 108 11、event 对象的常见应用?(必会) 109 12、自定义事件/ 模拟事件?(必会) 109 13、通用事件绑定/ 编写一个通用的事件监听函数?(必会) 110 14、dom 和 bom 的区别(必会) 111 15、事件三要素(必会) 111 16、事件执行过程(必会) 111 17、获取元素位置(必会) 112 18、封装运动函数(必会) 112 19、绑定事件和解除事件的区别(必会) 113 20、谈谈事件委托的理解?(必会) 114 21、 JavaScript 中的定时器有哪些?他们的区别及用法是什么?(必会) 114 22、比较 attachEvent 和 addEventListener?(必会) 115 23、document.write 和 innerHTML 的区别?(必会) 115 24、 什么是 window 对象?什么是 document 对象?(必会) 116 25、Js 拖动的原理?(必会) 118 26、描述浏览器的渲染过程,DOM 树和渲染树的区别(必会) 119 27、dom 树和 render 树之间的关系?(高薪常问) 119 28、获取到页面中所有的 CheckBox 怎么做(不适用第三方框架)?(高薪常问) 119 29、 简单说一下页面重绘和回流?(高薪常问) 119 30、如何最小化重绘(repaint)和回流(reflow)(高薪常问) 120 31、Js 延迟加载的方式有哪些?(了解) 120 32、IE 与
### 回答1: 要成为优秀的前端工程师,有以下几点建议: 1. 学习 HTML、CSS 和 JavaScript 这三门基础技术,掌握常用的语法和 API。 2. 熟悉常见的前端框架,如 React、Vue、Angular 等,并学会如何使用这些框架来构建 Web 应用。 3. 关注前端领域的最新发展,不断提升自己的技术水平。 4. 注重用户体验,学会使用工具来分析和优化网站的性能。 5. 注重代码质量,学会使用版本控制工具,并养成良好的编码习惯。 6. 善于沟通和协作,能够与后端工程师和产品经理等团队成员配合,共同完成项目。 ### 回答2: 要成为优秀的前端工程师,首先需要全面掌握前端技术。 首先,对HTML、CSS和JavaScript的基础语法要熟悉。掌握HTML的结构和标签,了解CSS的样式属性和选择器,学习JavaScript的基本语法和常用方法。此外,要了解Web标准和浏览器兼容性,以便编写优雅且兼容不同浏览器的代码。 其次,要学习掌握各种流行的前端框架和库,如React、Vue和Angular。这些框架能够提供更高效、可维护和具有良好用户体验的前端应用程序。 另外,要深入了解前端性能优化和调试技术。通过减少HTTP请求、压缩代码、使用合适的缓存策略等手段来提高网页加载速度和性能。同时,要熟悉主流浏览器的开发者工具,并能够利用这些工具进行代码调试和性能分析。 而且,要有良好的代码管理和团队合作能力。了解版本控制系统如Git,并掌握常用的代码管理工作流程,例如分支管理、合并和冲突解决。此外,学会与团队成员协作,合理分工、高效沟通,共同完成项目。 最后,要不断学习与研究前端技术的最新动态。前端技术发展迅速,时刻关注最新的前沿技术和趋势,参加行业研讨会和培训课程,积极参与开源社区,不断提升自己的技术能力。 总的来说,成为优秀的前端工程师需要不断学习和实践,掌握基础技术、深入了解前端框架、掌握性能优化和调试技术、具备良好的代码管理和团队合作能力,并保持对前端技术的持续学习和追求。 ### 回答3: 要成为优秀的前端工程师,需要具备以下几个方面的能力和品质。 首先,需要扎实的技术基础。前端工程师需要熟悉HTML、CSS和JavaScript等技术,并掌握各种前端框架和工具。通过学习相关教程和参与项目实践,不断提升自己的技术水平。 其次,要有优秀的问题解决能力。前端工程师常常面临各种问题和挑战,需要有快速分析和解决问题的能力。学会利用互联网资源,查询和学习相关知识,通过不断实践和调试,找出最佳解决方案。 第三,要有良好的团队合作意识。作为前端工程师,往往需要和UI设计师、后端工程师以及产品经理等其他团队成员紧密合作。要学会倾听他人的意见和建议,善于沟通和协作,共同完成项目任务。 此外,持续学习也是成为优秀前端工程师的必备品质。由于前端技术更新迅速,需要不断学习新的技术和工具,跟随行业的发展趋势。参加相关的培训课程、技术讲座和行业活动,加强自身的专业素养。 最后,为自己设定目标和规划发展路线。前端工程师职业发展广阔,可以从事移动端开发、前端架构设计、性能优化等不同领域。制定明确的职业规划,有针对性地学习和发展,提升自身的竞争力和专业能力。 总之,成为优秀的前端工程师需要不断学习和实践,具备扎实的技术基础、出色的问题解决能力和团队协作能力,同时保持持续学习和规划自我发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极光之夜。

谢谢~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值