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 相关文章推荐
js类中获取外部函数名的方法
Aug 19 Javascript
jquery通过visible来判断标签是否显示或隐藏
May 08 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
Mar 26 Javascript
TypeScript具有的几个不同特质
Apr 07 Javascript
jQuery控制网页打印指定区域的方法
Apr 07 Javascript
jQuery插件kinMaxShow扩展效果用法实例
May 04 Javascript
简单讲解jQuery中的子元素过滤选择器
Apr 18 Javascript
JavaScript动态数量的文件上传控件
Nov 18 Javascript
JS实现太极旋转思路分析
Dec 09 Javascript
Javascript面试经典套路reduce函数查重
Mar 23 Javascript
详解基于vue-cli优化的webpack配置
Nov 06 Javascript
jQuery实现鼠标响应式透明度渐变动画效果示例
Feb 13 jQuery
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
PHP实现文件安全下载
2006/10/09 PHP
php指定函数参数默认值示例代码
2013/12/04 PHP
PHP中的reflection反射机制测试例子
2014/08/05 PHP
PHP队列用法实例
2014/11/05 PHP
推荐5款跨平台的PHP编辑器
2014/12/25 PHP
PHP面向对象之事务脚本模式(详解)
2017/06/07 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
laravel 框架结合关联查询 when()用法分析
2019/11/22 PHP
用js一次改变多个input的readonly属性值的方法
2014/06/11 Javascript
JavaScript实现简单的二级导航菜单实例
2015/04/15 Javascript
jQuery CSS3相结合实现时钟插件
2016/01/08 Javascript
checkbox批量选中,获取选中项的值的简单实例
2016/06/28 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
JS多物体实现缓冲运动效果示例
2016/12/20 Javascript
jQuery+ajax的资源回收处理机制分析
2017/01/07 Javascript
在bootstrap中实现轮播图实例代码
2017/06/11 Javascript
nodejs模块学习之connect解析
2017/07/05 NodeJs
vue实现单选和多选功能
2017/08/11 Javascript
自己动手封装一个React Native多级联动
2018/09/19 Javascript
vue如何进行动画的封装
2018/09/26 Javascript
Node.js学习之内置模块fs用法示例
2020/01/22 Javascript
uniapp微信小程序实现一个页面多个倒计时
2020/11/01 Javascript
Python实现SMTP发送邮件详细教程
2021/03/02 Python
Python使用openpyxl读写excel文件的方法
2017/06/30 Python
Python实现京东秒杀功能代码
2019/05/16 Python
python 判断linux进程,并杀死进程的实现方法
2019/07/01 Python
python 调用pyautogui 实时获取鼠标的位置、移动鼠标的方法
2019/08/27 Python
python默认参数调用方法解析
2020/02/09 Python
Python使用tkinter制作在线翻译软件
2021/02/22 Python
TUMI新加坡官网:国际领先的商旅箱包品牌
2019/01/12 全球购物
四风问题自查报告剖析材料
2014/02/08 职场文书
公务员政审单位鉴定材料
2014/05/16 职场文书
客户答谢会活动方案
2014/08/31 职场文书
安全生产先进个人总结
2015/02/15 职场文书
2015年老干部工作总结
2015/04/23 职场文书
幼儿园托班开学寄语(2016秋季)
2015/12/03 职场文书