Js单个图片的延迟加载
一.图片的延迟加载在实际项目中经常出现,例如我们在浏览某宝,某东的商品时,可以发现,屏幕下面的图片有些时候并没有直接显示,这就是延迟加载的功效。例如下图:
当然,瑕不掩瑜,延迟加载在优化性能的效益也是有目共睹的,那今天我们先来学习一下其中最好理解的单张图片延迟加载。所需结构如下:
1.一个封装好的JS文件,用于获取设置偏移量和父级参照物,以下是代码,可自己封装或cv:
let utils = (function () {
function screen(attr, value) {
// 判断用户到底想干什么,如果用户只是传递了一个参数,那就是想获取,如果传递;两个参数,那就是想设置
if (value === undefined) {
// 这是获取值
return document.documentElement[attr] || document.body[attr];
}
else {
// 设置
document.documentElement[attr] = value;
document.body[attr] = value;
}
}
function offset(ele){
let left = ele.offsetLeft; // 获取当前盒子的做偏移量
let top = ele.offsetTop;
let parent = ele.offsetParent; // 获取当前盒子的父级参照物
while(parent !==document.body){
// 在原来的基础之上累加父级参照物的左border的宽度和父级参照物的左偏移量
left += parent.clientLeft + parent.offsetLeft;
top += parent.clientTop + parent.offsetTop;
// 继续获父级参照物的父级参照物
parent = parent.offsetParent;
}
return {
left,
top
}
}
return {
screen,
offset
}
})()
2.html部分,非常简单src先绑定一个等待图片,再写一个真实路径,用来在延迟加载之后替换图片,从而达到目的:
3.css部分:
简单写一点宽高即可
4.js部分
首先我们接收一下img,创建一个名为dealy的函数,当滚动条滚动时触发,在函数里用之前接收的img得到图片的总高和上偏移量,用导入的js文件得到浏览器的高和浏览器滚动条卷曲的高度,如果浏览器的高和浏览器滚动条卷曲的高度大于或等于图片的总高和上偏移量,证明已经达到了临界条件,图片下边框和浏览器可视窗口下边框重合,说明图片的此时应该显示出来了,因此需要通过getAtrrbute拿到img的真实路径存放在一个变量中,最后再将变量赋值给img的src,从而显示图片.
<script>
let img = document.getElementsByTagName('img')[0];
/*
图片的下边框 === 浏览器的下边框
当前图片的自身的高度+图片的上偏移量(距离body) === 当前浏览器的可视区域的高度+ 当前浏览器滚动条卷曲的高度
如果上述条件相等,说明已经到达临界条件
*/
function dealy() {
// 防止图片重新加载。
if (img.flag) {
return;
}
// 在这里去做图片是否显示
let screenH = utils.screen('clientHeight'); // 前浏览器的高度
let imgH = img.offsetHeight; // 图片的总高度
let imgT = utils.offset(img).top; // 图片的上偏移量(body)
let screenT = utils.screen('scrollTop'); // 浏览器滚动条的卷曲的高度
console.log(screenH, screenT, imgH, imgT);
if (screenT + screenH >= imgH + imgT) {
console.log('show');
// 把当前img元素行内的true-img的值拿过来,赋值给src就可以了
let address = img.getAttribute('true-img');
console.log(address);
img.src = address;
img.flag = true; // 只要图片已经加载过,就会拥有这个属性
}
}
window.onscroll = dealy;
</script>
因为滚动条每次滑动都会重新执行函数,这样非常浪费性能,所以我们在函数中给img增加自定义属性flag并赋值true,在函数执行前先判断是否为true,如果为true说明已经执行过,没必要再次执行