效果
可以看到我们的图片不是一次性加载的,而是当滚动条滚动的时候不断的加载新的图片。这就是懒加载。懒加载的好处有:
- 可以缓解服务器端的压力
- 可以节约用户的流量,有时候用户并不是要看所有的图片,只是看前面几张而已。
使用原生js实现图片懒加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html, body{
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
background-color: green;
display: flex;
flex-direction: column;
}
#header {
width: 100%;
height: 50px;
background-color: pink;
text-align: center;
flex: 0 0 auto;
}
#content {
width: 100%;
background-color: gray;
flex-grow: 1;
overflow: auto;
}
#imgContainer {
width: 80%;
margin-left: auto;
margin-right: auto;
padding: 30px;
background-color: hotpink;
}
img {
margin-bottom: 20px;
width: 100%;
}
#footer {
height: 50px;
background-color: pink;
text-align: center;
flex: 0 0 auto;
}
</style>
</head>
<body>
<!--
整体布局:
整体采用flex进行布局,上中下
中间的区域用于展示图片
content的高度是固定的
imgContainer的高度由其内部的图片撑起来
设置content的overflow为auto,所以当imgContainer过高时content会产生滚动条
主要思路就是:我们需要做的是判断页面还有多少在底部,如果快要滑到页面底部了,就去加载新的图片
-->
<div id="container">
<div id="header">
<h3>这是一个懒加载结合节流的例子</h3>
</div>
<div id="content">
<div id="imgContainer">
<!-- 这里放置动态添加的图片 -->
</div>
</div>
<div id="footer">
<h3>这是页面底部</h3>
</div>
</div>
</body>
<script>
window.onload = function () {
// 手写一个节流函数(也可以通过引入一些库函数来实现)
// 节流的作用是避免鼠标滑动时回调函数太过频繁的触发
// 节流可提高浏览器性能
function throttle(fn, delay){
let timer = null;
return function(){
let context = this;
let args = arguments;
if(!timer){
timer = setTimeout(()=>{
timer = null; // 重要
fn.apply(context,args)
},delay)
}
}
}
// 定义要进行懒加载的图片的路径(一般从后台返回的)
const arr = [
'./images/1.jpg',
'./images/2.jpg',
'./images/3.jpg',
'./images/4.jpg',
'./images/5.jpg',
'./images/6.jpg',
'./images/7.jpg',
'./images/8.jpg',
'./images/9.jpg',
'./images/10.jpg',
'./images/11.jpg',
'./images/12.jpg'
]
// 为content元素绑定滚动事件(这里使用了节流)
// 限制check_if_load_more_img函数300ms内只能被调用一次
document.getElementById('content').onscroll = throttle(check_if_load_more_img, 300)
// 首先就加载一次图片
loadImg()
// 定义一个函数用于判断当前滚动条是否快要到底部了 如果快到底部了 就加载图片
function check_if_load_more_img() {
const scrollHeight = document.getElementById("imgContainer").scrollHeight
const scrollTop = document.getElementById("content").scrollTop
const height = document.getElementById("content").clientHeight
console.log(scrollHeight, scrollTop, height)
let BottomPixels = scrollHeight-(scrollTop+height)
if (BottomPixels < 200) { // 还差200px就到底部了,加载图片
loadImg()
}
}
// 定义一个函数来加载图片
function loadImg() {
let fragment = document.createDocumentFragment();
let temp = arr.splice(0, 3) // 从arr中取出前3张图片进行加载(splice会影响原数组)
temp.forEach(function(item) {
let imgNode = document.createElement('img')
imgNode.src = item
fragment.appendChild(imgNode)
})
let imgContainer = document.getElementById("imgContainer")
imgContainer.appendChild(fragment)
}
}
</script>
</html>
计算原理
关键属性
Element.scrollTop: 一个元素的 scrollTop 值是这个元素的内容顶部(卷起来的)到它的视口可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。
Element.scrollHeight: 是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
Element.clientHeight: 它是元素内部的高度(单位像素),包含内边距,但不包括水平滚动条、边框和外边距。