前言
对于图片量比较大的点上首页APP等,在打开商品展示页面的时候需要再加大量图片,在这种场景下如果直接全量加载,必然会造成页面性能消耗过大,白屏或者卡顿,用户体验非常糟糕,用户真的需要我们显示所有图片一起展示吗?其实并不是,用户看到的只是浏览器可视区域的内容。所以从这个情况我们可以做一些优化,只显示用户可视区域内的图片,当用户触发滚动的瞬间再去请求显示给用户
图片懒加载的实现:
-
给所有需要展示的 img 标签添加自定义属性: data-src ,同时不要设置 src 属性,data-src的值为图片url。
-
当页面加载完后,我们需要获取所有需要懒加载的图片的元素集合,判断是否在可视区域,如果是在可视区域的话,再重新设置元素的src属性值为真正图片的地址。
-
可视化区域的判断:是通过获取元素的getBoundingClientRect属性的top值和页面的clientHeight进行对比,如果top值小于clientHeight,则说明元素出现在可视区域之内。
-
当用户滚动窗口的时候,此时应该通过每个元素的BoundingClientRect属性来判断元素是否出现在可视区域内,如果在可视区域内,就渲染图片展示在可是区域内。
懒加载的实现:
<!-- 只在可视化区域内加载图片 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body> <img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG"
> <img style="width: 250px;height: 250px;background-color: grey; display: block;"
src="https://juejin.cn/post/img/test01.PNG" > <img
style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
</body>
<script>
var viewHeight = document.documentElement.clientHeight; // 可视化区域的高度
var viewWidth = document.documentElement.clientWidth; // 可视化区域的宽度
function lazyload() { //获取所有要进行懒加载的图片
let eles = document.querySelectorAll('img[data-src]'); // 获取属性名中有data-src的
console.log('获取所有的信息', eles)
Array.prototype.forEach.call(eles, function (item, index) {
let rect;
if (item.dataset.src === '') {
return;
}
rect = item.getBoundingClientRect(); // 返回元素的大小及其相对于视口的位置
console.log('返回元素的大小及其相对于视口的位置', rect) //图片一进入可视区,动态加载
if (rect.bottom >= 0 && rect.top < viewHeight) {
! function () {
let img = new Image();
img.src = item.dataset.src;
img.onload = function () {
item.src = img.src;
}
item.removeAttribute('data-src');
}();
}
})
}
lazyload();
</script>
</html>
复制代码
上述代码中,我们已经初步完成图片懒加载,但是我们大家都知道,scroll这个事件,用户滚动鼠标就会触发很多次,这也会导致我们的性能急剧下降,所以这就引出了我们的混合体 防抖函数优化我们的性能:
function debounce(fn, gapTime) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
fn();
}, gapTime)
}
}
复制代码
最后贴出完整代码:
<!-- 只在可视化区域内加载图片 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img id="img" style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
<img style="width: 250px;height: 250px;background-color: grey; display: block;" src="https://juejin.cn/post/img/test01.PNG" >
</body>
<script>
var viewHeight = document.documentElement.clientHeight; // 可视化区域的高度
var viewWidth = document.documentElement.clientWidth; // 可视化区域的宽度
console.log('可视化区域的高度', viewHeight)
console.log('可视化区域的宽度', viewWidth)
let imgDom = document.getElementById('img');
console.log(window.getComputedStyle(imgDom, null).color); // 用来取所有的
function lazyload () {
//获取所有要进行懒加载的图片
let eles = document.querySelectorAll('img[data-src]'); // 获取属性名中有data-src的
console.log('获取所有的信息', eles)
Array.prototype.forEach.call(eles, function(item, index) {
let rect;
if(item.dataset.src === '') {
return;
}
rect = item.getBoundingClientRect(); // 返回元素的大小及其相对于视口的位置
console.log('返回元素的大小及其相对于视口的位置', rect)
//图片一进入可视区,动态加载
if(rect.bottom >= 0 && rect.top < viewHeight) {
!function () {
let img = new Image();
img.src = item.dataset.src;
img.onload = function () {
item.src = img.src;
}
item.removeAttribute('data-src');
}();
}
})
}
lazyload();
// 添加滚动事件触发图片加载
document.addEventListener('scroll', debounce(lazyload, 500), false);
// 通过函数防抖来持续优化:
function debounce(fn, gapTime) {
let timer = null;
return function() {
if(timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function() {
fn();
}, gapTime)
}
}
</script>
</html>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END