在项目中有时候会遇到一个页面上有很多很多图片,如果所有的图片一次性加载,那么对网络是有一定要求的,并且每次加载图片都会对服务器发出请求;
所以,懒加载归根结底就是想要优化前端性能,只显示可视窗口内的图片,这样对用户而言图片加载速度明显变快了,而且可以可以节省流量,对服务器而言可以减少服务器的性能开销,因为请求的次数变少了;
最终效果想要达到的是:每当图片快要进入可视窗口时,就加载图片,否则图片就不需要加载;
想要达到最终效果,流程大致需要以下几步:
//用一个立即执行函数将代码包裹起来,防止变量污染
(function(root,func,plugin){
func(jQuery,plugin)
})(this,function(jQuery,plugin){
//给$的fn添加一个名为prizeDraw的函数
$.fn[plugin] = function(params,offset) {
}
},'lazyload')
在这一步中需要获取所有的img元素,并且进行筛选,将已存在src属性并且src不为空的img元素进行过滤掉掉,并且如果img标签没有指定的属性,那么也过滤掉
//视窗高度
let windowHeight = () => $(window).height();
$.fn[plugin] = function (params,offset) {
if(!(typeof params === "string" && typeof offset === "number")) return;
//执行懒加载函数
lazyloadFunc(this,params,offset);
};
function lazyloadFunc(jqDom, params, offset){
//取得所有src为空,或者没有src属性的img元素
const imgfilter = imgfilterFunc(jqDom);
}
function imgfilterFunc(dom){
const arr = [];
for(let i = 0;i < dom.length;i++){
if(!$(dom[i]).attr("src") && $(dom[i]).attr("data-src")){
arr.push(dom[i])
}
}
return arr;
}
此时获得的imgfilter变量,就是所有需要实现懒加载的img元素
在这一步,需要对imgfilter变量中的所有img进行分类:
function lazyloadFunc(jqDom, params, offset){
//取得所有src为空,或者没有src属性的img元素
const imgfilter = imgfilterFunc(jqDom);
//对图片进行筛选
const imgObj = imgType(imgfilter, offset);
}
//将该网页上所有的img进行分类
//一种是已经在视窗内,需要马上加载显示的,另一种是不在视窗内,可以等滚动条滚动到接近的时候再显示
function imgType(arr, offset){
const arrtype = {
nowload:[],
lazyload:[]
};
//滚动条距离顶部的距离
let scrollTop = $(window).scrollTop();
for(let i = 0;i<arr.length;i++){
let item = $(arr[i]).offset().top;
//offset变量是设定的加载提前量,代表img在进入视窗内前offset像素时加载
if(item - scrollTop - offset > windowHeight()){
arrtype.lazyload.push(arr[i]);
}
else{
arrtype.nowload.push(arr[i]);
}
}
return arrtype;
}
返回的对象imgObj中就分好了,哪些是需要立刻加载的,哪些是可以等等加载的;
对imgObj中所有需要立刻加载的img进行加载
function lazyloadFunc(jqDom, params, offset){
//取得所有src为空,或者没有src属性的img元素
const imgfilter = imgfilterFunc(jqDom);
//对图片进行筛选
const imgObj = imgType(imgfilter, offset);
//立刻加载已在视窗内的
loadImgNow(imgObj.nowload, params);
}
//对需要加载的进行立刻加载
function loadImgNow(arr, params){
arr.forEach(el => {
$(el).attr("src",$(el).attr(params))
});
}
这个所谓的加载,就是将预设在data-src中的图片路径赋值给src属性,这样img就可以加载图片了
监听滚动事件,每一次滚动的时候,都会获得页面上所有还没有加载src的img元素,之后再对没有加载的img元素进行分类,判断哪些需要加载,哪些还可以等等
$.fn[plugin] = function (params,offset) {
if(!(typeof params === "string" && typeof offset === "number")) return;
lazyloadFunc(this,params,offset);
//监听滚动事件,再次执行加载事件
$(window).scroll(() => {
lazyloadFunc(this,params,offset);
})
};
在所有的图片都已经被加载玩了之后,每次滚动滚动条的时候,还会进行筛选,这显然是不可理的,既然所有图片都已经加载完了,那么此时就不需要再筛选数组了,因此加一个开关
$(window).scroll(() => {
if(flg){
lazyloadFunc(this,params,offset);
}
})
function lazyloadFunc(jqDom, params, offset){
//取得所有src为空,或者没有src属性的img元素
const imgfilter = imgfilterFunc(jqDom);
//如果图片进行筛选后,发现所有图片都有不为空的src属性了,那么就代表所有图片都已经加载完毕了
if(!imgfilter.length){
flg = false;
return;
}
//对图片进行筛选
const imgObj = imgType(imgfilter, offset);
//立刻加载已在视窗内的
loadImgNow(imgObj.nowload, params);
}
图片的懒加载想要解决的一个问题是优化前端的性能,能给用户带来更好的体验,同时可以减少服务器压力,因此如果项目中如果哪个页面存在大量的图片,那么就可以考虑引入懒加载机制,提高用户体验;