懒加载
为什么需要懒加载?
浏览器回流重绘完毕页面,指的是html,css加载完毕,但是图片需要发起新的网络请求,当页面图片过多或过大,会导致页面加载缓慢,影响用户体验.
如何实现懒加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img {
height: 300px;
display: block;
}
</style>
</head>
<body>
<img src="" data-src="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=1785207335,3397162108&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=2581522032,2615939966&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=245883932,1750720125&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=3423293041,3900166648&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=3241434606,2550606435&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=1417505637,1247476664&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=3659156856,3928250034&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=1416385889,2308474651&fm=193&f=GIF" alt="">
<img src="" data-src="https://t7.baidu.com/it/u=2469680087,3014121106&fm=193&f=GIF" alt="">
</body>
<script>
let height = window.innerHeight; //可视区域高度
//判断默认情况下应该展示哪些图片
function lazyLoad() {
let imgs = document.querySelectorAll('img[data-src]');
for (let i = 0; i < imgs.length; i++) {
let rect = imgs[i].getBoundingClientRect(); //获取图片在可视区域的位置信息
if (rect.top < height && rect.bottom > 0) {
let newImage = new Image(); //创建一个新的图片对象
newImage.src = imgs[i].getAttribute('data-src'); //设置新图片的src属性为data-src的值
newImage.onload = function () { //当新图片加载完成后
imgs[i].src = newImage.getAttribute('src'); //将新图片的src属性赋值给原图片的src属性
}
imgs[i].removeAttribute('data-src'); //移除图片的data-src属性,避免重复加载同一图片
}
}
}
lazyLoad()
window.addEventListener('scroll', lazyLoad)
</script>
</html>
这里我们img标签src不给值,将url放进data-src属性中,img中的src属性一旦给值就会自动发请求.在js中判定哪些图片出现在可视范围中.优先加载出现在可视范围中的图片,将data-src中的值给到src,最后移除data-src属性.在window上绑定滑动事件,不断触发函数.由于img标签上的data-src属性已被删除,所以不会再触发,避免重复加载同一图片.
缺点: 当图片过大时,图片出现在可视区域时,会有一段时间的白屏现象,影响用户体验
预加载
-预加载的原理:
-在加载页面的同时,用第二个线程去加载图片,当图片加载完毕时,将图片的资源交给第一个线程,从而实现图片的预加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="pic"></div>
<script>
let pic = document.getElementById('pic')
let arr = [
"https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF",
"https://t7.baidu.com/it/u=1785207335,3397162108&fm=193&f=GIF",
"https://t7.baidu.com/it/u=2581522032,2615939966&fm=193&f=GIF",
"https://t7.baidu.com/it/u=245883932,1750720125&fm=193&f=GIF",
"https://t7.baidu.com/it/u=3423293041,3900166648&fm=193&f=GIF",
"https://t7.baidu.com/it/u=3241434606,2550606435&fm=193&f=GIF",
"https://t7.baidu.com/it/u=1417505637,1247476664&fm=193&f=GIF",
"https://t7.baidu.com/it/u=3659156856,3928250034&fm=193&f=GIF",
"https://t7.baidu.com/it/u=1416385889,2308474651&fm=193&f=GIF",
"https://t7.baidu.com/it/u=2469680087,3014121106&fm=193&f=GIF",
]
// 创建一个新的线程
const worker = new Worker('./worker.js')
// 将数据发送给子线程
worker.postMessage(arr)
// 接收子线程发送的数据
worker.onmessage = function (e) {
console.log(e.data);
const img = new Image()
// console.log(window.URL.createObjectURL(e.data));
img.src = window.URL.createObjectURL(e.data)//需要将子线程传过来的图片文件对象Blob转成URL地址,这里我们使用window.URL.createObjectURL这个api进行转换。
pic.appendChild(img)
}
</script>
</body>
</html>
self.onmessage = function(e) {
// console.log(e.data);
// 将数组中的地址资源加载出来
let arr = e.data;
for (let i = 0; i < arr.length; i++) {
let xhr = new XMLHttpRequest();
xhr.open("get", arr[i], true);
xhr.responseType = 'blob' // 文件类型
xhr.send();
xhr.onload = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(xhr.response);
self.postMessage(xhr.response);
}
}
}
}
-缺点:
同一时间加载多张图片,对服务器压力较大