持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
前言
接前几天讲解了DOM、BOM的基础知识后,用原生js实现图片懒加载。
图片懒加载
图片懒加载是前端页面优化的一种方式,在页面中有很多图片的时候,图片加载就需要很多时间,很耗费服务器性能,不仅影响渲染速度还会浪费带宽,为了解决这个问题,提高用户体验,所以就出现了懒加载这种方式来减轻服务器的压力,优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。
图片懒加载如何实现
- 简单来说就是当js监听到图片元素进入到可视窗口的时候,将自定义属性中的地址存储到src中,达到懒加载的效果
- 先将img标签中的src链接设置为空,将真正的图片链接放在自定义属性(data-src)
具体实现思路
如上图,y代表整个页面的高度,x代表滚动条滚动的距离,z代表当前可视化窗口,w代表未加载的img图片,而我们需要操作的就是当前所展示的图片的offsetTop(元素到顶部的距离) 小于等于 窗口的高度+滚动条滚动的高度,我们就展示图片。
- 伪代码:offsetTop+clientLeft < =(document.documentElement.clientHeight)+(window.pageYOffset)
懒加载实现效果图
<!DOCTYPE html>
<html lang="en">
<body>
<div class="outer"></div>
</body>
<script>
var oOuter = document.querySelector('.outer');
var imgSrc =[
'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a93ce8141c284e5f8f9fb9ed860e0115~tplv-k3u1fbpfcp-watermark.image?',
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2935181e76cf4ad080544771d1dc309f~tplv-k3u1fbpfcp-watermark.image?',
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/713934abf3d44ebfbe4ac977c77cd85c~tplv-k3u1fbpfcp-watermark.image?',
'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/18a58263915a4a91becda50af6aba75a~tplv-k3u1fbpfcp-watermark.image?',
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/63e1ce8d64474c18bcb09313683a704b~tplv-k3u1fbpfcp-watermark.image?',
'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7d0020d9bbc24d66a2f659b5a29aaee2~tplv-k3u1fbpfcp-watermark.image?',
'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bfb1c1f1496d4900a7be1a9011c19b68~tplv-k3u1fbpfcp-watermark.image?',
'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7533eb9af02c4c61a9836ca09d2f6583~tplv-k3u1fbpfcp-watermark.image?',
'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aeceee670f1b42b8869d302e4b52466a~tplv-k3u1fbpfcp-watermark.image?',
'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23fff46aff734773b5c73cd24182d7fb~tplv-k3u1fbpfcp-watermark.image?',
'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bfb1c1f1496d4900a7be1a9011c19b68~tplv-k3u1fbpfcp-watermark.image?',
'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7533eb9af02c4c61a9836ca09d2f6583~tplv-k3u1fbpfcp-watermark.image?',
'https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aeceee670f1b42b8869d302e4b52466a~tplv-k3u1fbpfcp-watermark.image?',
'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23fff46aff734773b5c73cd24182d7fb~tplv-k3u1fbpfcp-watermark.image?',
];
imgSrc.forEach(function(item){
var newImg = new Image
//先把src保存在当前img的自定义属性上,等加载到的时候,在把自定义属性给到src属性
newImg.src = 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4d4c7b477430450189b3cf4b9e887252~tplv-k3u1fbpfcp-watermark.image'
newImg.dataset.src = item;
oOuter.appendChild(newImg)
})
var oImgs = document.querySelectorAll('.outer img');
function lazyLoad() {
//获取窗口的高度
var winHeight = document.documentElement.clientHeight;
//获取滚动条已经滚动的距离
var winScroll = window.pageYOffset;
//遍历所有的图片
oImgs.forEach(function (item) {
//判断哪一个图片已经进入页面(图片距离文档顶部的值 小于 屏幕的高度加上滚动条滚过的距离)
if (getEleToDoc(item).top <= winHeight + winScroll) {
//让图片显示 把当前img标签上保存的data-src 赋值给img的src
item.src = item.dataset.src;
}
})
}
//监听滚动条
window.onload = window.onscroll = throttle(lazyLoad, 200);
//获取元素到文档顶部或左侧边缘的距离封装
function getEleToDoc(Ele) {
var l = 0,
t = 0;
var obj = Ele;
while (obj) {
if (obj === Ele) {
l += obj.offsetLeft;
t += obj.offsetTop;
} else {
l += (obj.offsetLeft + obj.clientLeft);
t += (obj.offsetTop + obj.clientTop);
}
//如果obj存在,并且已经获取过值了,则把obj变成 原来obj的offsetParent
obj = obj.offsetParent;
}
return {
left: l,
top: t
}
}
//节流函数
function throttle(fn, time) {
//绑定事件的时候,先初始化一个上一次的事件
var lastTime = 0;
//这个函数是事件触发的时候真正调用的事件函数
return function () {
//当允许通过的时候 再调用真正的逻辑代码move
var nowTime = Date.now();
if (nowTime - lastTime < time) {
return;
}
lastTime = nowTime;
//arguments所在的函数就是真正的事件函数,所以拥有实参event 把event事件对象传递给fn move中就可以使用event事件对象了
// fn(arguments[0]);
//改变了fn的this为事件触发的对象
fn.call(this, arguments[0])
}
}
</script>
<style>
.outer {
width: 1040px;
margin: 0 auto;
border: 1px solid #000;
display: flex;
flex-wrap: wrap;
}
.outer img {
width: 500px;
height: 300px;
margin: 10px;
}
</style>
</html>
好了,以上就是本篇文章的分享,感谢阅读!