文章代码可在这里下载.css
先不给图片设置 src
属性值, 当图片进入浏览器窗口的时,给图片的src
属性赋值, 开始请求图片并渲染至屏幕。html
data-src
属性来保存正确的图片连接,将src
属性设置为空(或默认图片连接)src
属性赋予正确的值如今有一个须要解决的问题:怎么知道图片是否在视窗以内呢?git
能够这样判断:当图片的底部和页面的顶部的距离小于视窗的底部和页面的顶部的距离时就能够认为图片已经进入视窗了。这样提及来有些绕,用图片来看看会更清晰。api
当视窗在下拉过程当中其底部低于图片的底部时,就认为图片已经要加载了: 数组
为方便说明,先实现单张图片的懒加载,使用 JQuery库来完成。浏览器
JQuery的api中能够获取到视窗的高度、视窗顶部和页面顶部的距离,两者相加就是视窗底部和页面顶部的距离;一样的,也能够得到图片包裹层的高度和它的顶部到页面顶部的距离,相加就是图片包裹层底部到页面顶部的距离。网络
将以上两者比较,就能够肯定图片是否须要被加载。app
DOM结构框架
<div class="wrap-single">
<img src="" data- src="http://img1.imgtn.bdimg.com/it/u=461406802,1565444607&fm=26&gp=0.jpg">
</div>
复制代码
图片初始样式ui
img {
width: 100%;
display: none;
/* 加载以前先隐藏 */
}
复制代码
JQuery代码
let $wrap = $('.wrap-single'),
img = $wrap.children('img'),
$window = $(window);
$window.on('load scroll', function(e) { // 同时监听 加载完成和滚动 事件
if(img.attr('is-loaded') === 'true') { // 当图片被打上已加载的标记时再也不进行请求
return ;
}
// 获取图片容器自己的高度 + border-top距离body 顶部的高度
let wrapBottomDist= $wrap.outerHeight() + $wrap.offset().top;
// 获取视窗自己的高度 + 视窗顶部距离 body 顶部的高度
let windowBottomDist = $window.outerHeight() + $window.scrollTop();
// 判断图片容器是否已在视窗之中
if(wrapBottomDist <= windowBottomDist) {
// 如果,则取得真实图片地址并设置给 src 属性
let realSrc = img.attr('data-src');
img.attr('src', realSrc);
// 当图片加载完成时,设置图片显示,并标记图片已经加载完成
img.on('load', () => {
img.css('display', 'block');
img.attr('is-loaded', true); // 利用自定义属性打上加载完成的标记
});
}
});
复制代码
效果以下:
可见只有当图片彻底进入窗口时才会开始请求图片,同时从右侧能够看出当图片进入窗口是才会发出对图片连接的请求。
在有了单张图片懒加载的基础后,实现多张图片的懒加载就容易多了。直接给出代码吧,代码中有详细的注释:
DOM 结构
<div class="wrap">
<h1>A Lazy Load Demo</h1>
<div class="img-wrapper">
<img src="" data-src="http://img1.imgtn.bdimg.com/it/u=461406802,1565444607&fm=26&gp=0.jpg">
</div>
<!-- 省略多行一样的代码 -->
<div class="img-wrapper">
<img src="" data-src="http://img1.imgtn.bdimg.com/it/u=461406802,1565444607&fm=26&gp=0.jpg">
</div>
</div>
复制代码
JQuery 代码
let $boxes = $('.img-wrapper'),
$window = $(window),
imgs = [], // 保存每张图片的对象
wrapBottomDist = []; // 保存每张图片底部与 body 顶部的距离
$boxes.each((index, item) => { // 处理数组 imgs 和 wrapBottomDist
let $item = $(item);
imgs.push($item.children('img'));
wrapBottomDist.push($item.outerHeight() + $item.offset().top); // 获取图片容器自己的高度 + border-top距离body 顶部的高度
});
function lazy() { // 事件处理程序
// 判断是否须要继续执行
if(!wrapBottomDist.length || !wrapBottomDist[wrapBottomDist.length - 1]) {
return ;
}
// 获取视窗自己的高度 + 视窗顶部距离 body 顶部的高度
let windowBottomDist = $window.outerHeight() + $window.scrollTop();
// 一次判断每张图片是否已经进入视窗
wrapBottomDist.forEach((pos, index) => {
if(pos < windowBottomDist) {
let img = imgs[index];
img.attr('src', img.attr('data-src'));
img.on('load', () => {
img.css('display', 'block');
});
wrapBottomDist[index] = undefined; // 将已经进入视窗的项进行标记
}
});
}
$window.on('load scroll', lazy); // 注册事件处理程序
复制代码
效果
若有错误,敬请指出,谢谢~