实现原理

  1. 结构中,我们使用一个盒子包裹着图片(图片不显示的时候,可以先占据着这个位置,并且设置默认背景图或背景颜色)
  2. 最开始,img 的 src 设置默认背景图,并把图片真实地址放到自定义属性中(比如:data-src )
  3. 当 JS 监听到该图片元素进入可视窗口时,将自定义属性中的地址放到 src 属性中,达到懒加载效果

作用:

  1. 防止页面一次性向服务器发送大量请求,导致页面卡顿
  2. 全部加载会耗费大量流量

预备知识:

  1. clientHeight:当前盒子可视区域的高度(height+上下padding)
  2. offsetHeight:获取当前盒子的总高度(height+上下padding+上下border)
  3. offsetTop:当前盒子距离父级参照物的上偏移量
  4. offsetParent:当前盒子的父级参照物
  5. scrollTop:获取和设置当前盒子纵向滚动条卷曲的高度

代码实现

为了显示更加明显,当图片的下边框 = 浏览器可视窗口的下边框时,显示图片真实路径

  • 图片下边框:图片距离 body 的上偏移量 + 图片自身的总高度
  • 浏览器可视窗口下边框:浏览器滚动条卷曲高度 + 当前浏览器可视窗口的高度

单张图片懒加载

<!DOCTYPE html>
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>单张图片延时加载</title><style>* {margin: 0;padding: 0;}img {width: 100%;height: 100%;}#box {width: 300px;height: 200px;margin: 800px auto;}</style>
</head><body><div id="box"><img src="img/default.jpg" true-img="img/1.jpg" alt="" /></div>
</body>
<script src="utils.js"></script>
<script>let box = document.getElementById("box");let img = document.getElementsByTagName("img")[0];function check() {// 让图片只加载一次if (img.flag) {return;}// 当前图片盒子的总高度let boxH = box.offsetHeight;// 获取当前图片盒子距离 body 上偏移量let boxT = utils.offset(box).top;// 获取浏览器可视区域高度let winH = utils.win("clientHeight");// 获取浏览器滚动条卷曲高度let winT = utils.win("scrollTop");if (winH + winT >= boxH + boxT) {// 创建一个 img 标签let newImg = new Image();let trueImg = img.getAttribute("true-img");newImg.src = trueImg;// 动态创建一个 img 标签用来检测当前的路径是否正确newImg.onload = function () {// 如果路径正确,执行onload函数img.src = trueImg;img.flag = true;newImg = null;};newImg.onerror = function () {// 如果路径错误,执行onerror函数img.src = "img/2.jpg";img.flag = true;};}}window.onscroll = check;
</script>
</html>

多张图片懒加载

这里使用 getElementsByClassName ,这个具有映射关系,下面简单介绍一下这个映射关系:

getElementsByClassName 返回对象是动态的 HTMLCollection

  • 动态 添加/删除 元素 HTMLCollection 的长度会产生变化

    • 把最后一个 li,从 ul 中删除,lis的长度 -1
    • 删除的属性,lis 中访问不到
<ul id="lists"><li class="bg">1</li><li>2</li><li>3</li><li id="end">4</li>
</ul>
<script>var lis = document.getElementsByTagName("li");lis[0].classList.remove("bg");lists.removeChild(end);console.log(lis.length); // 3console.log(lis[0].classList); // DOMTokenList [value: ""]
</script>

uerySelectorAll 返回对象是静态 NodeList

  • 动态 添加/删除 元素 NodeList 的长度不会产生变化

    • 把最后一个 li,从 ul 中删除,lis的长度并没有 -1
    • 删除的属性,lis 中访问不到
<ul id="lists"><li class="bg">1</li><li>2</li><li>3</li><li id="end">4</li>
</ul>
<script>var lis = document.querySelectorAll("li");lis[0].classList.remove("bg");lists.removeChild(end);console.log(lis.length); // 4console.log(lis[0].classList); // DOMTokenList [value: ""]
</script>
<!DOCTYPE html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.box {margin: 500px auto;}.box img {display: block;margin: auto;margin-bottom: 10px;height: 200px;}</style>
</head><body><div class="box"><img src="img/default.jpg" class="bg" true-img="img/1.jpg" alt=""><img src="img/default.jpg" class="bg" true-img="img/2.jpg" alt=""><img src="img/default.jpg" class="bg" true-img="img/3.jpg" alt=""><img src="img/default.jpg" class="bg" true-img="img/4.jpg" alt=""><img src="img/default.jpg" class="bg" true-img="img/5.jpg" alt=""></div>
</body></html>
<script src="utils.js"></script>
<script>// 动态的 HTMLCollection 具有映射关系let imgs = document.getElementsByClassName("bg");// 判断每一张图片是否要加载function delay() {// 当函数执行的时候,循环每一张图片,然后判断每一张图片是否需要加载for (var i = 0; i < imgs.length; i++) {delayImg(imgs[i]);}}function delayImg(img) {let imgH = img.offsetHeight;let winH = utils.win("clientHeight");let imgT = utils.offset(img).top;let winT = utils.win("scrollTop");if (winT + winH > imgH + imgT) {let trueSrc = img.getAttribute("true-img");let newImg = new Image();newImg.src = trueSrc;newImg.onload = function () {img.src = trueSrc;img.className = "";newImg = null;};}}// 刚进界面把已经符合的图片显示出来delay();window.onscroll = delay;
</script>
<script src="pratice2.js"></script>

utils

let utils = (function () {// 获取盒子距离body的偏移量function offset(el) {let left = el.offsetLeft;let top = el.offsetTop;let parent = el.offsetParent;while (parent !== document.body) {left += parent.offsetLeft + parent.clientLeft;top += parent.offsetTop + parent.clientTop;parent = parent.offsetParent;}return {left,top,};}// 设置或者获取浏览器的某些属性function win(attr, val) {if (val == undefined) {return document.documentElement[attr] || document.body[attr];}document.documentElement[attr] = val;document.body[attr] = val;}return {offset,win,};
})();

JS 实现图片延迟加载(懒加载)相关推荐

  1. 如何使用echo.js实现图片的懒加载(整理)

    如何使用echo.js实现图片的懒加载(整理) 一.总结 一句话总结:a.在img标签中添加data-echo属性加载真实图片:<img class="loading" sr ...

  2. 图片的懒加载和预加载?

    一.写在前面 图片的懒加载和图片的预加载都是前端性能优化的一个方案,当然可能存在不同的应用场景,下面我们将总结一下这两个方案. 二.图片懒加载 图片的懒加载是什么? 图片的懒加载指的是在长网页中延迟加 ...

  3. 【JavaScript】图片的懒加载

    [JavaScript]图片的懒加载 文章目录 [JavaScript]图片的懒加载 1. 懒加载 2. 利用`scroll`事件 利用`HTMLElement.offsetTop` 利用`Eleme ...

  4. 图片的懒加载是怎么实现的

    图片的懒加载是怎么实现的 为什么要使用懒加载? 对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB.当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载 ...

  5. 移动端图片居多,加载过慢,使用延迟加载|懒加载( lazyload.js)

    文章目录[隐藏] Lazy Load 插件原理 开始使用 lazyload.js lazyload.js 高级使用方法: 更周全的做法 提前加载 自定义触发事件 自定义显示效果 把图像插入某个容器 加 ...

  6. jquery 当页面图片加载之后_图片的懒加载和预加载

    一.懒加载 [1.1]什么是懒加载? 懒加载也就是延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式.当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1 ...

  7. 图片的懒加载与预加载

    懒加载 懒加载:也叫延迟加载,指的是在长网页中延迟加载图片的时机,当用户需要访问时,再去加载,这样可以提高网站的首屏加载速度,提升用户的体验,并且可以减少服务器的压力. 懒加载的实现原理是:将页面上图 ...

  8. js原生实现高性能懒加载(分步解析)

    小弟不才,自己做了一个简单的懒加载,为了节约 window.onscroll的次数 ,提高性能, 设计了函数节流和函数防抖两种模式 , 后面想到更好的方法会更新,也请各位朋友多多指点!! :D 废话不 ...

  9. Mybatis学习第四天:Mybatis延迟加载懒加载,一级缓存,二级缓存,注解开发

    文章目录 Mybatis中的延迟加载 一对一进行延迟加载 一对多的延迟加载 缓存机制: 一级缓存 二级缓存 注解开发 注解开发--单表的增删改查 注解开发--建立表与实体类的对应关系 注解开发--多表 ...

  10. JS 实现图片的预加载(转载)

    图片预加载是web开发中一种应用相当广泛的技术,比如我们在做图片翻转显示等特效的时候,为了让图片在转换的时候不出现等待,我们最好是先让图片下载到本地,然后在继续执行后续的操作. 下面的函数实现了一个我 ...

最新文章

  1. 习题3-3 数数字(Digit Counting , ACM/ICPC Danang 2007, UVa1225)
  2. mysql的隔离级别_MySQL的四种事务隔离级别
  3. js 遍历对象的几种方法
  4. 修改mysql数据引擎的方法- 提高数据库性能
  5. 【Spark】Spark Stream读取kafka写入kafka报错 AbstractMethodError
  6. Python风格总结: 复制列表
  7. 若依如何调整首页左侧菜单栏宽度
  8. SQL SERVER 如何把1列多行数据 合并成一列显示
  9. java 基础数据结构源码详解及数据结构算法
  10. Win7/Win8/IIS7/IIS8配置ASP/ACCESS
  11. 车牌识别代码学习笔记
  12. 实施工程师的发展前景
  13. 剪贴板是计算机系统,剪贴板怎么打开,小编教你电脑剪贴板怎么打开
  14. 前缀和差分 精讲(一维、二维、附例题!)
  15. org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont.addNewFamily()
  16. 商络转债上市价格预测
  17. Head First Java(中文版)pdf
  18. CSS3:clip-path详解
  19. 小白学Pytorch系列-- Torch API (5)
  20. VMWare快照原理(写时复制)?快照保护、快照克隆的作用?

热门文章

  1. javascript 正则 判断电话号码格式
  2. 基于OpenDaylight和OVSDB搭建VxLAN网络
  3. 如何使用Floccus + 坚果云管理自己的浏览器书签
  4. 怎样混好嵌入式/MCU/ARM/DSP这一行?
  5. 总结几个简单好用的Python人脸识别算法
  6. 事件之触摸及手势事件
  7. 人员定位助力智慧安全建设,化工厂实施人员定位管理迫在眉睫
  8. 在小程序中使用阿里巴巴矢量图标库
  9. 2023年天津专升本报名缴费考试时间汇总
  10. PHYSIONET 心电数据库