小弟不才,自己做了一个简单的懒加载,为了节约 window.onscroll的次数 ,提高性能, 设计了函数节流和函数防抖两种模式 , 后面想到更好的方法会更新,也请各位朋友多多指点!! :D
废话不多说,直接亮代码~~
1.简单懒加载:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documenttitle>
<style>
img{
display: block;
max-height: 300px;
}
style>
head>
<body>
<div class="container">
<h1>懒加载页面h1>
<img src="1.png" data-src='1.jpg' alt="">
<img src="1.png" data-src='2.jpg' alt="">
<img src="1.png" data-src='3.jpg' alt="">
<img src="1.png" data-src='4.jpg' alt="">
<img src="1.png" data-src='5.jpg' alt="">
<img src="1.png" data-src='6.jpg' alt="">
<img src="1.png" data-src='7.jpg' alt="">
<img src="1.png" data-src='8.jpg' alt="">
<img src="1.png" data-src='9.jpg' alt="">
div>
body>
html>
<script>
var scrollTop = window.scrollY;
var imgs = Array.from(document.querySelectorAll('img'));
lazyLoad();
window.onscroll = () => {
scrollTop = window.scrollY;
lazyLoad();
}
function lazyLoad(){
imgs.forEach((item,index)=>{
if( item.offsetTop < window.innerHeight + scrollTop ){
console.log(item.offsetTop)
item.setAttribute('src',item.dataset.src)
}
})
}
script>
这里有坑请注意!!! 而且这个问题不好百度 - . -
如果复制上面的代码,首次加载进页面发现所有图片均已经加载完毕,没有实现懒加载的效果
因为函数调用时img.onload没有完成,img元素没有高度!!!
解决办法是在外层套一个window.onload
window.onload = function(){
lazyLoad();
}
2.函数节流throttle懒加载
推荐!!!高频滚动模式下, 每隔一段时间才会实现渲染~~
实现原理是 加入一个开关变量, 控制每隔固定的一段时间,函数才可能被触发~
window.onload = function(){
var scrollTop = window.scrollY;
var imgs = Array.from(document.querySelectorAll('img'));
lazyLoad();
//函数节流模式
var canRun = true;
window.onscroll = () => {
if( !canRun ){
return
}
canRun = false;
setTimeout(()=>{
scrollTop = window.scrollY;
lazyLoad();
canRun = true;
},1000)
}
function lazyLoad(){
imgs.forEach((item,index)=>{
if( item.offsetTop < window.innerHeight + scrollTop ){
console.log(item.offsetTop)
item.setAttribute('src',item.dataset.src)
}
})
}
}
为了逻辑清晰 , 打包成函数调用:
window.onload = function(){
var scrollTop = window.scrollY;
var imgs = Array.from(document.querySelectorAll('img'));
lazyLoad();
let canRun = true;//开关变量用于函数节流
window.addEventListener('scroll',throttle(lazyLoad,500));
//定义懒加载函数 , 从上到下懒加载 , 从下到上也是懒加载
function lazyLoad(){
imgs.forEach((item,index)=>{
if( scrollTop===0 && item.dataset.src !== '' && item.offsetTop < window.innerHeight + scrollTop ){
alert()
item.setAttribute('src',item.dataset.src)
item.setAttribute('data-src','')
}else if( item.dataset.src !== '' && item.offsetTop < window.innerHeight + scrollTop && item.offsetTop > scrollTop ){
item.setAttribute('src',item.dataset.src)
item.setAttribute('data-src','')
}
})
}
//定义函数节流函数
function throttle(fun,delay){
return function(){
// fun();
if( !canRun ){
return
}
console.log('!!!')
canRun = false;
setTimeout(()=>{
scrollTop = window.scrollY;
fun(imgs);
canRun = true
},delay)
}
}
}
3.函数防抖debounce
原理是设置clearTimeout和setTimeout,的dalayTime控制一个事件如果频繁触发,将只会执行最近的一次… 可以用在用户注册时候的手机号码验证和邮箱验证。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语。以下还是以页面元素滚动监听的例子
效果:一直滑动的时候,将不会有图片加载, 停下后300ms会加载
window.onload = function(){
var scrollTop = window.scrollY;
var imgs = Array.from(document.querySelectorAll('img'));
lazyLoad();
//函数防抖模式
var timer = null;
window.onscroll = () => {
clearTimeout(timer);
timer = setTimeout(()=>{
scrollTop = window.scrollY;
lazyLoad();
},300)
}
function lazyLoad(){
imgs.forEach((item,index)=>{
if( item.offsetTop < window.innerHeight + scrollTop ){
console.log(item.offsetTop)
item.setAttribute('src',item.dataset.src)
}
})
}
}
4.最终版 throttle + debounce
完美懒加载
注意点: 在滚动条下拉状态下刷新页面, 页面实现更新渲染之后会立马触发滚动条事件,回到上一次页面的停留点,但是并不是从scrollTop为0的位置出发~
window.onload = function(){
var scrollTop = window.scrollY;
var imgs = Array.from(document.querySelectorAll('img'));
lazyLoad();
// 采用了节流函数
window.addEventListener('scroll',throttle(lazyLoad,500,1000));
function throttle(fun, delay, time) {
var timeout,
startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果达到了规定的触发时间间隔,触发 handler
console.log(curTime - startTime)
if (curTime - startTime >= time) {
fun();
startTime = curTime;
// 没达到触发间隔,重新设定定时器
} else {
timeout = setTimeout(fun, delay);
}
};
};
// 实际想绑定在 scroll 事件上的 handler
// 需要访问到imgs , scroll
function lazyLoad(){
scrollTop = window.scrollY;
imgs.forEach((item,index)=>{
if( scrollTop===0 && item.dataset.src !== '' && item.offsetTop < window.innerHeight + scrollTop ){
// alert()
item.setAttribute('src',item.dataset.src)
item.setAttribute('data-src','')
}else if( item.dataset.src !== '' && item.offsetTop < window.innerHeight + scrollTop && item.offsetTop > scrollTop ){
item.setAttribute('src',item.dataset.src)
item.setAttribute('data-src','')
}
})
}
}