本文详细介绍了一种基于JavaScript的图片懒加载实现方案。通过监听页面滚动事件,判断图片是否进入可视区域,动态将data-src赋值给src属性,从而减少初始加载时间并节约带宽。文章提供了完整的代码示例及针对iScroll等滚动库的扩展方法,帮助开发者提升网页加载性能。
前言
图片懒加载原理与HTML约定
在各类网络论坛及以图片展示为主的网站上,普遍采用一种称为懒加载的技术。其核心机制是:当页面请求加载时,仅渲染可视区域内的图片,其余图片暂不加载。只有当用户滚动页面使图片进入可视范围时,才动态触发加载。这种方式有效节省了网络带宽,并显著提升了页面的首次加载速度。
Web图片懒加载的实现原理是:遍历页面上的img元素,读取其data-src属性(也可自定义其他属性名)中存储的图片地址,并将其赋值给img的src属性,以此完成图片的动态加载。
需要注意的是,在初始化阶段不应直接设置src属性。因为即使设置了src='' ,浏览器仍会尝试立即加载图片,从而失去懒加载的意义。
实现一个基础的图片懒加载功能主要涉及两个关键环节。
1. HTML 约定
我们首先需要给准备实施懒加载的img元素添加指定的class 这里为m-lazyload ,同时将img src赋值给 data-src属性。
具体示例为:
<img class="m-lazyload" data-src="imgUrl">
JavaScript实现步骤
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的值赋予该图片的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]);
}
};
})();
总结
以上就是这篇文章的全部内容,希望本文的内容对大家学习或者使用图片懒加载的时候能有所帮助,如果有疑问大家可以留言交流。