懒加载也叫延迟加载,即延迟加载图片或者符合某种条件时才加载某些图片。牺牲了服务器前端性能,换取更好的用户体验,这样可以使用户的操作得到最快的响应。
预加载是提前加载图片,当用户需要查看时可以直接从本地缓存中渲染。作为服务器前端的优化,减少请求次数或者延迟请求。
本质:两者的行为是相反的,一个是提前加载,一个是迟缓加载甚至是不加载,懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端的压力。
懒加载实现
实现方式:可视区加载。即仅加载用户可以看到的区域,这个主要是由监控滚动条来实现,一般会在距离用户看到某图片前一定距离便开始加载,这样能保证用户拉下时正好能看到图片。
Tips
- 自定义属性,以
data-
为前缀,可以通过绑定的DOM对象的dataset来获取自定义属性的值。 - DOM API
getBoundingClientRect
:这个API会返回一个对象,蓝色区域表示DOM实际所在的地方,top属性表示元素顶端距离视口顶端的位置。
- 不能直接给
img
标签设置src
属性
<div class = 'container'>
<img src = '' alt='lazy-load' data-src = '图片实际的url地址'>
... //此处略去多个相同的img标签。
<img src = '' alt='lazy-load' data-src = '图片实际的url地址'>
</div>
-----------------------------------------------------------------------------------------
<script>
//所有具有data-src属性的图片都需要懒加载。
function lazyLoad(defaultImg){
//第0步,先得到所有需要懒加载的图片
var imgs = document.querySelectorAll('img[data-src]');
//将其转化为真正的数组
imgs = Array.from(imgs);
//设置默认图片
setDefaultImgs();
//懒加载所有图片
loadAllImgs();
//监听滚动条
var timer = null;
document.body.onscroll = function(){
//函数防抖
if(timer){
clearTimeOut(timer);
}
timer = setTimeOut(function(){
loadAllImgs();
},500)
}
--------------------------------------函数区----------------------------------------------
setDefaultImgs(){
if(!defaultImg){
return ;
}
imgs.forEach(item=>item.src =defaultImg )
}
function loadAllImgs(){
imgs.forEach((item,index)=>{
if(loadImg(item)){
imgs.splice(index,1);
index--;
}
})
}
/*
*懒加载一张图片,自行判断是否应该加载
*img:图片的dom对象
*/
function loadImg(img){
//判断该图片是否能够加载。实际上时判断该图片是否在可视区范围内
var rect = img.getBoundingClientRect();
if(rect.bottom<=0){
return false;
}
if(rect.top>=document.documentElement.clientHeight){
return false
}
img.src = img.dataset.src;
//判断是否由原图
if(img.dataset.original){
img.onload = function(){
img.src = img.dataset.original;
img.onload = null;//不写这一步就会导致无限循环。因为小图加载完触发onlod时间后,大图加载完又触发onload事件。
}
}
return true
}
}
</script>
预加载实现
核心原理是浏览器请求过的资源会有缓存,所以使用js创建一个看不见的img标签,浏览器就会发出请求,这个过程用户是看不见的,到了页面上真正要显示这张图片的时候,浏览器一检查之前缓存过,就不会再向服务器发出请求,直接从缓存中获取,给用户的感觉就是秒加载了。
function preloadImg(url) {
var img = new Image();
img.src = url;
if(img.complete) {//如果有缓存
//接下来可以使用图片了
//do something here
}
else {
img.onload = function() {
img.onload = null;
//接下来可以使用图片了
//do something here
};
}
}