图片懒加载
场景
一个网页会包含很多的图片,例如淘宝京东这些购物网站,商品图片很多,如果在首页就全部加载的话,会影响渲染速度(比如出现白屏)和浪费带宽,为了解决以上问题,提高用户体验,就出现了懒加载方式来减轻服务器的压力,优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。
原理
一张图片就是一个img标签,浏览器是否发起请求图片是根据img的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给img的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。
实现
- 加载loading图片进行占位
- 判断哪些图片要加载
- 将loading图片替换真图片
<body>
<div class="img-list">
<img src="./loading.gif" data-src="1.jpg" width="300" height="300">
<img src="./loading.gif" data-src="2.jpg" width="300" height="300">
<img src="./loading.gif" data-src="3.jpg" width="300" height="300">
<img src="./loading.gif" data-src="4.jpg" width="300" height="300">
<img src="./loading.gif" data-src="5.jpg" width="300" height="300">
<img src="./loading.gif" data-src="6.jpg" width="300" height="300">
<img src="./loading.gif" data-src="7.jpg" width="300" height="300">
</div>
<script>
// 节流
function throttle(fn, interval, option) {
var lastTime = 0
var timer
var option = option || {}
var trailing = option.trailing || false
return function () {
var _this = this
var _arguments = arguments
var newTime = new Date().getTime()
if (timer) {
clearTimeout(timer)
}
var result
return new Promise((resolve, reject) => {
if (newTime - lastTime > interval) {
result = fn.apply(_this, _arguments)
resolve(result)
lastTime = newTime
} else if (trailing) {
timer = setTimeout(() => {
result = fn.apply(_this, _arguments)
resolve(result)
}, interval);
}
})
}
}
// 懒加载
function lazy() {
// 获取页面滚动条卷去的高度
let bodyScrollHeight = parseInt(document.body.scrollTop || document.documentElement.scrollTop)
// 获取页面高度
let windowHeight = window.innerHeight
// 获取所有img标签
var imgs = document.querySelectorAll('img')
// 延迟加载图片
setTimeout(() => {
for (let i = 0; i < imgs.length; i ) {
// 获取每个img标签距离body的高度
let imgScrollTop = imgs[i].offsetTop
/*
(1)如果img标签距离body的高度 小于 页面高度 被卷去的高度,则代表当前img标签在可视区域,加载图片
(2)由于如果从最底部加载的话,最开头的图片一定符合(1),因此要判断img标签距离body的高度有没有大于滚动的高度,
大于滚动高度了才加载图片
*/
if (imgScrollTop >= bodyScrollHeight && imgScrollTop < windowHeight bodyScrollHeight) {
// 遍历img的所有属性
for (let j = 0; j < imgs[i].attributes.length; j ) {
// 如果有data-src属性,将它的值赋给src
if (imgs[i].attributes[j].name == 'data-src') {
imgs[i].src = imgs[i].attributes[j].value
// 赋值后data-src就没用了,移除掉它
imgs[i].removeAttribute('data-src')
}
}
}
}
}, 300);
}
// 刚进首页不触发滚动事件,因此要先加载一次
lazy()
// 监听滚动事件
// window.addEventListener('scroll', lazy)
// 用节流函数优化性能
window.addEventListener('scroll', throttle(lazy, 100, { trailing: true }))
</script>
</body>