JS实现图片懒加载(lazyload)过程详解


Posted in Javascript onApril 02, 2020

对于图片较多的页面,使用懒加载可以大幅提高页面加载速度,提高用户体验。

懒加载的意义(为什么要使用懒加载)

对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB。当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,也许会失去很多的用户。

所以,对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样子对于页面加载性能上会有很大的提升,也提高了用户体验。

原理

将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名,我才用data-src)属性指向真实的图片。src指向一张默认的图片,否则当src为空时也会向服务器发送一次请求。可以指向loading的地址。

注:图片要指定宽高

<img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" />

当载入页面时,先把可视区域内的img标签的data-src属性值负给src,然后监听滚动事件,把用户即将看到的图片加载。这样便实现了懒加载。

代码

<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    img {
      display: block;
      margin-bottom: 50px;
      width: 400px;
      height: 400px;
    }
  </style>
</head>

<body>

  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
  <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">
  <img src="default.jpg" data-src="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt="">

</body>

JavaScript

<script>
  var num = document.getElementsByTagName('img').length;
  var img = document.getElementsByTagName("img");
  var n = 0; //存储图片加载到的位置,避免每次都从第一张图片开始遍历

  lazyload(); //页面载入完毕加载可是区域内的图片

  window.onscroll = lazyload;

  function lazyload() { //监听页面滚动事件
    var seeHeight = document.documentElement.clientHeight; //可见区域高度
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //滚动条距离顶部高度
    for (var i = n; i < num; i++) {
      if (img[i].offsetTop < seeHeight + scrollTop) {
        if (img[i].getAttribute("src") == "default.jpg") {
          img[i].src = img[i].getAttribute("data-src");
        }
        n = i + 1;
      }
    }
  }
</script>

jQuery

<script>
  var n = 0,
    imgNum = $("img").length,
    img = $('img');

  lazyload();

  $(window).scroll(lazyload);

  function lazyload(event) {
    for (var i = n; i < imgNum; i++) {
      if (img.eq(i).offset().top < parseInt($(window).height()) + parseInt($(window).scrollTop())) {
        if (img.eq(i).attr("src") == "default.jpg") {
          var src = img.eq(i).attr("data-src");
          img.eq(i).attr("src", src);

          n = i + 1;
        }
      }
    }
  }
</script>

使用节流函数进行性能优化

如果直接将函数绑定在scroll事件上,当页面滚动时,函数会被高频触发,这非常影响浏览器的性能。

我想实现限制触发频率,来优化性能。

节流函数:只允许一个函数在N秒内执行一次。下面是一个简单的节流函数:

// 简单的节流函数
//fun 要执行的函数
//delay 延迟
//time 在time时间内必须执行一次
function throttle (fun, delay, time) {
 let timeout

 let startTime = new Date()

 return function () {
  let context = this

  let args = Array.prototype.slice.call(arguments)

  let curTime = new Date()

  clearTimeout(timeout)
  if (curTime - startTime >= time) {
   // 如果达到了规定的触发时间间隔,触发 handler
   fun.apply(context, args)
   startTime = curTime
  } else {
   // 没达到触发间隔,重新设定定时器
   timeout = setTimeout(function () {
    fun.apply(context, args)
   }, delay)
  }
 }
};
// 实际想绑定在 scroll 事件上的 handler
function lazyload(event) {}
// 采用了节流函数
window.addEventListener('scroll',throttle(lazyload,500,1000));

使用去抖函数进行性能优化

去抖相比较节流函数要稍微简单一点,去抖是让函数延迟执行,而节流比去抖多了一个在一定时间内必须要执行一次。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery实现的下拉和收缩效果示例
Aug 21 Javascript
JS+CSS实现模仿浏览器网页字符查找功能的方法
Feb 26 Javascript
jQuery实现为图片添加镜头放大效果的方法
Jun 25 Javascript
jQuery插件formValidator实现表单验证
May 23 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
Jul 13 Javascript
web3.js增加eth.getRawTransactionByHash(txhash)方法步骤
Mar 15 Javascript
说说Vuex的getters属性的具体用法
Apr 15 Javascript
iSlider手机端图片滑动切换插件使用详解
Dec 24 Javascript
JS实现网页烟花动画效果
Mar 10 Javascript
基于js实现逐步显示文字输出代码实例
Apr 02 Javascript
微信小程序自定义联系人弹窗
May 26 Javascript
ant-design表单处理和常用方法及自定义验证操作
Oct 27 Javascript
JavaScript运动原理基础知识详解
Apr 02 #Javascript
基于js实现逐步显示文字输出代码实例
Apr 02 #Javascript
webpack3.0升级4.0的方法步骤
Apr 02 #Javascript
Javascript模块化机制实现原理详解
Apr 02 #Javascript
sharp.js安装过程中遇到的问题总结
Apr 02 #Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
Apr 01 #jQuery
Selenium执行Javascript脚本参数及返回值过程详解
Apr 01 #Javascript
You might like
防止用户利用PHP代码DOS造成用光网络带宽
2011/03/01 PHP
PHP CURL或file_get_contents获取网页标题的代码及两者效率的稳定性问题
2015/11/30 PHP
给大家分享几个常用的PHP函数
2017/01/15 PHP
28个JS验证函数收集
2010/03/02 Javascript
node.js超时timeout详解
2014/11/26 Javascript
JS实现漂亮的淡蓝色滑动门效果代码
2015/09/23 Javascript
深入理解jQuery 事件处理
2016/06/14 Javascript
如何使用headjs来管理和异步加载js
2016/11/29 Javascript
关于AngularJs数据的本地存储详解
2017/01/20 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
js实现水平滚动菜单导航
2017/07/21 Javascript
浅谈angular2路由预加载策略
2017/10/04 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
Vue-component全局注册实例
2018/09/06 Javascript
nodejs中express入门和基础知识点学习
2018/09/13 NodeJs
javascript删除数组元素的七个方法示例
2019/09/09 Javascript
Javascript中Math.max和Math.max.apply的区别和用法详解
2020/08/24 Javascript
webpack4从0搭建组件库的实现
2020/11/29 Javascript
Python实现采用进度条实时显示处理进度的方法
2017/12/19 Python
python 通过 socket 发送文件的实例代码
2018/08/14 Python
Python中拆分字符串的操作方法
2019/07/23 Python
python中seaborn包常用图形使用详解
2019/11/25 Python
opencv 图像轮廓的实现示例
2020/07/08 Python
Python基于内置函数type创建新类型
2020/10/22 Python
中国一家专注拼团的社交购物网站:拼多多
2018/06/13 全球购物
Farfetch台湾官网:奢侈品牌时尚购物平台
2019/06/17 全球购物
德国高尔夫商店:Par71.de
2020/11/29 全球购物
成都思必达公司C#程序员招聘面试题
2013/06/26 面试题
建筑系毕业生自我鉴定
2014/01/24 职场文书
市场部经理岗位职责
2014/04/10 职场文书
关于环保的演讲稿
2014/05/10 职场文书
自主招生推荐信怎么写
2015/03/26 职场文书
详解PHP用mb_string处理windows中文字符
2021/05/26 PHP
OpenCV全景图像拼接的实现示例
2021/06/05 Python
Python学习之异常中的finally使用详解
2022/03/16 Python
Java数组详细介绍及相关工具类
2022/04/14 Java/Android