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 实例一(first)
Mar 16 Javascript
Jquery $.getJSON 在IE下的缓存问题解决方法
Oct 10 Javascript
jQuery 回调函数(callback)的使用和基础
Feb 26 Javascript
javascript数组排序汇总
Jul 07 Javascript
简介BootStrap model弹出框的使用
Apr 27 Javascript
jQuery实现的兼容性浮动层示例
Aug 02 Javascript
AngularJS基础 ng-keydown 指令简单示例
Aug 02 Javascript
jQuery 检查某个元素在页面上是否存在实例代码
Oct 27 Javascript
Bootstrap基本组件学习笔记之分页(12)
Dec 08 Javascript
vue使用jsonp抓取qq音乐数据的方法
Jun 21 Javascript
vue 实现axios拦截、页面跳转和token 验证
Jul 17 Javascript
为vue项目自动设置请求状态的配置方法
Jun 09 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
Can't create/write to file 'C:\WINDOWS\TEMP\...MYSQL报错解决方法
2011/06/30 PHP
PHP输出数组中重名的元素的几种处理方法
2012/09/05 PHP
php ci框架中加载css和js文件失败的原因及解决方法
2014/07/29 PHP
php实现在新浪云中使用imagick生成缩略图并上传的方法
2016/09/26 PHP
ThinkPHP实现简单登陆功能
2017/04/28 PHP
深入理解PHP的远程多会话调试
2017/09/21 PHP
jquery 弹出层注册页面等(asp.net后台)
2010/06/17 Javascript
JS检测图片大小的实例
2013/08/21 Javascript
php析构函数的具体用法小结
2014/03/11 Javascript
JavaScript对象之深度克隆介绍
2014/12/08 Javascript
jQuery动画效果实现图片无缝连续滚动
2016/01/12 Javascript
详解nodejs 文本操作模块-fs模块(五)
2016/12/23 NodeJs
vue-router 组件复用问题详解
2018/01/22 Javascript
利用CDN加速react webpack打包后的文件详解
2018/02/22 Javascript
用vue2.0实现点击选中active其他选项互斥的效果
2018/04/12 Javascript
为jquery的ajax请求添加超时timeout时间的操作方法
2018/09/04 jQuery
jQuery实现input[type=file]多图预览上传删除等功能
2019/08/02 jQuery
layui的面包屑或者表单不显示的解决方法
2019/09/05 Javascript
JavaScript如何把两个数组对象合并过程解析
2019/10/10 Javascript
echarts实现折线图的拖拽效果
2019/12/19 Javascript
Vue项目利用axios请求接口下载excel
2020/11/17 Vue.js
[02:30]DOTA2放量测试专访海涛:呼吁保护新手玩家
2013/08/26 DOTA
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
Python输出9*9乘法表的方法
2015/05/25 Python
python先序遍历二叉树问题
2017/11/10 Python
使用urllib库的urlretrieve()方法下载网络文件到本地的方法
2018/12/19 Python
python opencv摄像头的简单应用
2019/06/06 Python
django 连接数据库 sqlite的例子
2019/08/14 Python
python3将变量写入SQL语句的实现方式
2020/03/02 Python
python3.7调试的实例方法
2020/07/21 Python
奥地利汽车配件店:Pkwteile.at
2017/03/10 全球购物
Lee牛仔裤澳大利亚官网:美国著名牛仔裤品牌
2017/09/02 全球购物
学校社会实践活动总结
2014/07/03 职场文书
python实现三阶魔方还原的示例代码
2021/04/28 Python
python中的sys模块和os模块
2022/03/20 Python