Skip to main content

图片懒加载?

图片懒加载是当页面的图片进入到用户的可视范围之内在加载图片的一种优化方式。

原理

在页面初始化的时候,<img>图片的 src 实际上是放在 data-src 属性上的,当元素处于可视范围内的时候,就把 data-src 赋值给 src 属性,完成图片加载。

// 在一开始加载的时候
<img data-src="http://xx.com/xx.png" src="" />

// 在进入可视范围内时
<img data-src="http://xx.com/xx.png" src="http://xx.com/xx.png" />

实现图片懒加载

预览地址:http://js.jirengu.com/fucasuvaje/1/watch?html,css,js,output

在懒加载的实现中,有两个关键的数值:

  • 一个是当前可视区域的高度
    //现代浏览器及 IE9 以上的浏览器:window.innerHeight
    //低版本的 IE 中:document.documentElment.clientHeight
    const viewHeight = window.innerHeight || document.documentElement.clientHeight
  • 一个是元素距离可视区域顶部的高度。

    Element.getBoundingClientRect():方法返回元素的大小及其相对于视口的位置。 返回的属性中有一个相对于可视区域顶部的高度也就是top属性,刚好就是我们需要的元素距离顶部的距离。

我们利用当前可视区域的高度大于等于元素距离可视区域顶部的高度就可以确定,该元素是否已经进入到了可视范围

image.png

<div class="container">
<div class="img">
<!-- 注意我们并没有为它引入真实的src -->
<img class="pic" alt="加载中" data-src="https://tse1-mm.cn.bing.net/th/id/OIP.8OrEFn_rKe82kqAWFjTuMwHaEo?pid=Api&rs=1" />
</div>
...
</div>
const imgs = document.getElementsByTagName('img')

const viewHeight = window.innerHeight || document.documentElement.clientHeight //视图高度

let num = 0 //为了避免重复加载图片,声明全局计数

function lazyload() {
console.log('滚动...')
for (let i = num; i < imgs.length; i++) {
// 用可视区域高度减去元素顶部距离可视区域顶部的高度
let distance = viewHeight - imgs[i].getBoundingClientRect().top
// 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
if (distance >= 0) {
// 给元素写入真实的src,展示图片
imgs[i].src = imgs[i].getAttribute('data-src')
// 前i张图片已经加载完毕,下次从第i+1张开始检查是否露出,为了避免滚动时重复加载图片
num = i + 1
}
}
}

// 节流函数
function throttle(fn, delay) {
let canuse = true
return function (...args) {
if (canuse) {
fn.call(this, args)
canuse = false
setTimeout(() => {
canuse = true
}, delay)
}
}
}

// 页面初始化:加载首屏图片
window.onload = lazyload
// 监听Scroll事件,为了防止频繁调用,使用防抖函数优化一下
window.addEventListener('scroll', throttle(lazyload, 100), false)

参考文章

https://segmentfault.com/a/1190000024547276 > https://www.zhangxinxu.com/wordpress/2016/06/image-preload-based-on-user-behavior/ > https://www.jianshu.com/p/a9aa268867f9