Javascript实现图片懒加载插件的方法


Posted in Javascript onOctober 20, 2016

前言

网络上各大论坛,尤其是一些图片类型的网站上,在图片加载时均采用了一种名为懒加载的方式,具体表现为,当页面被请求时,只加载可视区域的图片,其它部分的图片则不加载,只有这些图片出现在可视区域时才会动态加载这些图片,从而节约了网络带宽和提高了初次加载的速度,具体实现的技术并不复杂,下面分别对其说明。

Web 图片的懒加载就是通过读取img元素,然后获得img元素的data-src(也可以约定为其他属性名)属性的值,并赋予img的src,从而实现动态加载图片的机制。

这里需要注意的是: img在初始化的时候不要设置src属性,因为即使设置 src='' 浏览器也会尝试加载图片。

一个简单的图片懒加载共涉及两个方面

1. HTML 约定

我们首先需要给准备实施懒加载的img元素添加指定的class 这里为m-lazyload ,同时将img src赋值给 data-src属性。

具体示例为:

<img class="m-lazyload" data-src="imgUrl">

2. JavaScript 实现

动态加载总共分为以下几个步骤,这里每个步骤都将被拆分为独立的函数

1. 添加页面滚动监听事件

window.addEventListener('scroll', _delay, false);

function _delay() {
 clearTimeout(delay);
 delay = setTimeout(function () {
 _loadImage();
 }, time);
}

2. 当触发监听事件时会执行 _loadImage 函数,该函数负责加载图片

function _loadImage() {
 for (var i = imgList.length; i--;) {
 var el = imgList[i];
 if (_isShow(el)) {
  el.src = el.getAttribute('data-src');
  el.className = el.className.replace(new RegExp("(\\s|^)" + _selector.substring(1, _selector.length) + "(\\s|$)"), " ");
  imgList.splice(i, 1);
 }
 }
}

虽然执行了_loadImage函数,但是我们得知道哪些图片需要被加载,这里的判断依据是什么呢?

依据就是判断该图片是否在当前窗口的可视区域内,在这里我们封装一个_isShow函数来实现

function _isShow(el) {
 var coords = el.getBoundingClientRect();
 return ( (coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset));
}

自此一个图片加载的闭环就形成了

当网页滚动的事件被触发 -> 执行加载图片操作 -> 判断图片是否在可视区域内 -> 在,则动态将data-src的值赋予该图片。

太简单了?

事实就是如此!!!

如此简单,不妨扩展一下

添加一些自定义参数,谁都喜欢自定义,不是吗?

支持iScroll, iScroll是一个高性能,资源占用少,无依赖,多平台的javascript滚动插件。

这里我们做了些优化

图片加载后移除选择器,避免重复判断。

缓存img元素结合,减少dom元素查询性能损耗

扩展prototype添加getNode方法,支持分页数据懒加载(由于我们之前缓存了dom元素)

OK!说了这么多,show me the code 吧!

(function () {
 var imgList = [], // 页面所有img元素集合
 delay, // setTimeout 对象
 offset, //偏移量,用于指定图片距离可视区域多少距离,进行加载
 time, // 延迟载入时间
 _selector; // 选择器 默认为 .m-lazyload

 function _isShow(el) {
 var coords = el.getBoundingClientRect();
 return ( (coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset));
 }

 function _loadImage() {
 for (var i = imgList.length; i--;) {
  var el = imgList[i];
  if (_isShow(el)) {
  el.src = el.getAttribute('data-src');
  el.className = el.className.replace(new RegExp("(\\s|^)" + _selector.substring(1, _selector.length) + "(\\s|$)"), " ");
  imgList.splice(i, 1);
  }
 }
 }

 function _delay() {
 clearTimeout(delay);
 delay = setTimeout(function () {
  _loadImage();
 }, time);
 }

 function ImageLazyload(selector, options) {
 var defaults = options || {};
 offset = defaults.offset || 0;
 time = defaults.time || 250;
 _selector = selector || '.m-lazyload';
 this.getNode();
 _delay();//避免首次加载未触发touch事件,主动触发一次加载函数
 if (defaults.iScroll) {
  defaults.iScroll.on('scroll', _delay);
  defaults.iScroll.on('scrollEnd', _delay);
 } else {
  window.addEventListener('scroll', _delay, false);
 }
 }
 ImageLazyload.prototype.getNode = function () {
 imgList = [];
 var nodes = document.querySelectorAll(_selector);
 for (var i = 0, l = nodes.length; i < l; i++) {
  imgList.push(nodes[i]);
 }
 };
})();

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用图片懒加载的时候能有所帮助,如果有有疑问大家可以留言交流。

Javascript 相关文章推荐
extjs 为某个事件设置拦截器
Jan 15 Javascript
ExtJS PropertyGrid中使用Combobox选择值问题
Jun 13 Javascript
Jquery刷新页面背景图片随机变换的实现方法
Mar 15 Javascript
javascript特殊用法示例介绍
Nov 29 Javascript
自己使用jquery写的一个无缝滚动的插件
Apr 30 Javascript
让JavaScript中setTimeout支持链式操作的方法
Jun 19 Javascript
javascript中Array()数组函数详解
Aug 23 Javascript
JS实现网页每隔3秒弹出一次对话框的方法
Nov 09 Javascript
js如何判断输入字符串长度
Dec 16 Javascript
JS去掉字符串前后空格或去掉所有空格的用法
Mar 25 Javascript
详解vue express启动数据服务
Jul 05 Javascript
实例讲解JS中pop使用方法
Jan 27 Javascript
Vue.js Ajax动态参数与列表显示实现方法
Oct 20 #Javascript
探究Vue.js 2.0新增的虚拟DOM
Oct 20 #Javascript
Javascript 创建类并动态添加属性及方法的简单实现
Oct 20 #Javascript
javascript匀速动画和缓冲动画详解
Oct 20 #Javascript
js设置和获取自定义属性的方法
Oct 20 #Javascript
js阻止冒泡和默认事件(默认行为)详解
Oct 20 #Javascript
浅谈JS中String()与 .toString()的区别
Oct 20 #Javascript
You might like
swfupload 多文件上传实现代码
2008/08/27 PHP
Windows中使用计划任务自动执行PHP程序实例
2014/05/09 PHP
PHP中对各种加密算法、Hash算法的速度测试对比代码
2014/07/08 PHP
thinkPHP实现签到功能的方法
2017/03/15 PHP
php实现socket推送技术的示例
2017/12/20 PHP
javascript数组使用调用方法汇总
2007/12/08 Javascript
JS 动态获取节点代码innerHTML分析 [IE,FF]
2009/11/30 Javascript
jQuery 处理表单元素的代码
2010/02/15 Javascript
javascript XMLHttpRequest对象全面剖析
2010/04/24 Javascript
JS模拟自动点击的简单实例
2013/08/08 Javascript
基于jquery实现的自动补全功能
2015/03/12 Javascript
jQuery实现的指纹扫描效果实例(附演示与demo源码下载)
2016/01/26 Javascript
JS与Ajax Get和Post在使用上的区别实例详解
2016/06/08 Javascript
jQuery 全选 全部选 反选 实现代码
2016/08/17 Javascript
Nodejs进阶:基于express+multer的文件上传实例
2016/11/21 NodeJs
详解js中call与apply关键字的作用
2016/11/21 Javascript
ES6中Proxy与Reflect实现重载(overload)的方法
2017/03/30 Javascript
Easyui在treegrid添加控件的实现方法
2017/06/23 Javascript
4个顶级开源JavaScript图表库
2018/09/29 Javascript
[08:47]2018国际邀请赛 OG战队举杯时刻
2018/08/29 DOTA
python求素数示例分享
2014/02/16 Python
python实现360的字符显示界面
2014/02/21 Python
Python中运行并行任务技巧
2015/02/26 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
python中reduce()函数的使用方法示例
2017/09/29 Python
如何在python字符串中输入纯粹的{}
2018/08/22 Python
PyQt5+requests实现车票查询工具
2019/01/21 Python
Python实现封装打包自己写的代码,被python import
2020/07/12 Python
在python3.9下如何安装scrapy的方法
2021/02/03 Python
世界第一曲奇连锁店:Mrs. Fields Cookies
2017/02/04 全球购物
美国滑雪和滑雪板商店:Buckman
2018/03/03 全球购物
浙大网新C/C++面试解惑
2015/05/27 面试题
文秘专业自荐信
2013/10/14 职场文书
公司行政主管岗位职责
2015/04/09 职场文书
2016年119消防宣传日活动总结
2016/04/05 职场文书
2019通用版新员工入职培训方案!
2019/07/11 职场文书