原生JS写一个节流的懒加载图片,看代码(内注释)
HTML与CSS:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>懒加载优化</title>
<style>
img {
display: block;
margin-bottom: 50px;
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<img
src=""
data-src="https://hbimg.huabanimg.com/f200e018796d35a4144aa10d0d110103c8fcc78ed249-DFbWH2_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/337ba5b4bdeb60424ff9a758916540d95df715dd14798-dXXEXw_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/cd035f3f04dc34fefb06346eb08cb1129f3d442d1484e-lSh6d4_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/4a1a6234b081d381556945932b83a027aecb5cf0118e9-ILTxuX_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/7d3aac39f17a06e31ecfb657d6144cfefda1f0f113b75-L0lfEt_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/dcdb22813f06d4a73bcfbbb1ca13586ac1646944ada7-aKSZYQ_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/1f1745e56fb485bfa7c13075980758abc560d7c411e2f-npWToS_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/0114dd748c2c5ae1c54ca16b267a8b328c6fc0e06c1fc-TQkU6H_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/b1072e40de9af7af7833072a20e189f8e95385d547c06-TgAOvK_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/0ecf203179ace35cd8be7e8ad36ca8d1acac40422301d-2c5h7Q_fw658"
/>
<img
src=""
data-src="https://hbimg.huabanimg.com/7b37eef440e69b9e791ebbf06f2f86ad535543481647e-qHASHA_fw658"
/>
</body>
</html>
JavaScript:
var num = document.getElementsByTagName('img').length
var img = document.getElementsByTagName('img')
var n = 0 //存储图片加载到的位置,避免每次都从第一张图片开始遍历
var isLoadImg = false // 是否当前容器/页面里的图片加载完成
var _clientHeight = document.documentElement.clientHeight //可见区域高度
var _scrollTop =
document.documentElement.scrollTop || document.body.scrollTop //滚动条距离顶部高度
// 监听窗口变化重新计算可是区域
function computedClientHeight() {
_clientHeight = document.documentElement.clientHeight //可见区域高度
}
//页面载入完毕加载可是区域内的图片
lazyload()
function lazyload() {
// 获取滚动条距离顶部高度
isLoadImg = n >= num
_scrollTop = document.documentElement.scrollTop || document.body.scrollTop
for (var i = n; i < num; i++) {
if (img[i].offsetTop < _clientHeight + _scrollTop) {
if (img[i].getAttribute('src') == '') {
img[i].src = img[i].getAttribute('data-src')
}
console.log(5)
n = i + 1
}
}
}
/**
* 简单的节流函数throttle
* @param {*}
* fun 要执行的函数
* delay 延迟
* time 在time时间内必须执行一次
* flag 是否继续触发节流函数 (根据需求自定义,这里就是想当加载完图片时不需要进行多余的执行--优化)
*/
function throttle(fun, delay, time, flag) {
var timeout,
startTime = new Date()
return function() {
if (isLoadImg) return
var context = this,
args = arguments,
curTime = new Date()
clearTimeout(timeout)
// 如果达到了规定的触发时间间隔,触发 fun
if (curTime - startTime >= time) {
fun.apply(context, args)
startTime = curTime
// 没达到触发间隔,重新设定定时器
} else {
timeout = setTimeout(function() {
fun.apply(context, args)
}, delay)
}
}
}
/**
* 简单的防抖函数debounce
* @param {*}
* fun 要执行的函数
* wait 触发函数的时间间隔
*/
function debounce(fun, wait) {
var timer = null // 创建一个标记用来存放定时器的返回值
return function() {
clearTimeout(timer) // 每当用户输入的时候把前一个 setTimeout clear 掉
timer = setTimeout(function() {
// 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 wait 时间内如果还有字符输入的话,就不会执行 fun 函数
fun.apply(this, arguments)
}, wait)
}
}
// 使用了节流函数~实现性能较好的懒加载
window.addEventListener('scroll', throttle(lazyload, 500, 1000, isLoadImg))
// 使用了防抖函数~优化不断触发的窗口变化
window.addEventListener('resize', throttle(computedClientHeight, 800))
可以复制运行一下,通过加输出语句+控制台查看内部执行效果,如有错误/更好的方法,欢迎指正/指教~
↓ ↓ ↓ 想深入 节流与防抖 原理的可以戳 ↓ ↓ ↓