为什么浏览器需要懒加载 :
- 假设情况 : 页面之中有一千张图片,有一些是在显示区域内的,有一些是在显示区域外的;
因为浏览器加载图片是没有先后限制的,统一发起请求,谁先加载完就先渲染谁,资源分配随机, 会导致不好的用户体验。 - 懒加载: 让浏览器把性能放在显示区域内去进行数据的加载。
第一种
HTML结构
基于jQuery实现的懒加载
注意:图片的 src 需要修改为 data-lazy-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>
<style>
img {
display: block;
margin-bottom: 200px;
}
</style>
<body>
<img data-lazy-src="./images/P_000.jpg" alt="">
<img data-lazy-src="./images/P_001.jpg" alt="">
<img data-lazy-src="./images/P_002.jpg" alt="">
<img data-lazy-src="./images/P_003.jpg" alt="">
<img data-lazy-src="./images/P_004.jpg" alt="">
<img data-lazy-src="./images/P_005.jpg" alt="">
<img data-lazy-src="./images/P_006.jpg" alt="">
<img data-lazy-src="./images/P_007.jpg" alt="">
<img data-lazy-src="./images/P_008.jpg" alt="">
<img data-lazy-src="./images/P_009.jpg" alt="">
<img data-lazy-src="./images/P_010.jpg" alt="">
<img data-lazy-src="./images/P_011.jpg" alt="">
<img data-lazy-src="./images/P_012.jpg" alt="">
<img data-lazy-src="./images/P_013.jpg" alt="">
<img data-lazy-src="./images/P_014.jpg" alt="">
<img data-lazy-src="./images/P_015.jpg" alt="">
<img data-lazy-src="./images/P_016.jpg" alt="">
<img data-lazy-src="./images/P_017.jpg" alt="">
<img data-lazy-src="./images/P_018.jpg" alt="">
<img data-lazy-src="./images/P_019.jpg" alt="">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="./js/EasyLazyload.min.js"></script>
<script>
//调用函数
lazyLoadInit({
showTime: 1000,
onLoadBackEnd: function (i, e) {
console.log("onLoadBackEnd:" + i);
},
onLoadBackStart: function (i, e) {
console.log("onLoadBackStart:" + i);
}
});
</script>
</body>
</html>
EasyLazyload.min.js 文件
! function (t) {
function o(o, a, i) {
var n, c, e = new Image;
return e.src = o, e.onload = function () {
a(e.width, e.height), r.onLoadBackStart(i, t("img[data-lazy-src]:eq(" + i + ")"))
}, [n, c]
}
function a(a, n) {
var c = l.eq(a).attr("data-lazy-src");
o(c, function () {
try {
i(t("img[data-lazy-src]:eq(" + a + ")"), a, n)
} catch (t) {}
}, a)
}
function i(o, a, i) {
if (!o.attr("data-comp")) {
o.css("visibility", "hidden"), o.attr("src", o.attr("data-lazy-src"));
var c = o.width(),
e = o.height(),
d = o.offset().top,
f = o.offset().left;
o.css("visibility", "visible"), t("body").append("<div class='meng-lazy-div" + a + "' style='background-color: " + r.coverColor + ";position:absolute;width:" + c + "px;height:" + e + "px;top:" + d + "px;left:" + f + "px;z-index:500'>" + r.coverDiv + "</div>"), n(a, i, o), o.attr("data-comp", "true")
}
}
function n(o, a, i) {
t(".meng-lazy-div" + o).animate({
opacity: "0"
}, r.showTime, function () {
t(this).remove(), r.onLoadBackEnd(o, i), a()
})
}
function c() {
var o = t(document).scrollTop(),
i = [];
l.each(function (a) {
var n = t(this);
n.attr("data-comp") || n.offset().top - o + r.offsetTopm >= 0 && n.offset().top - o < s + r.offsetBottom && i.push(a)
}), 0 != i.length && a(i[0], function () {
c()
})
}
function e() {
c()
}
function d(o) {
r = t.extend(r, o), l.each(function () {
var o = t(this).attr("data-lazy-src");
f.push(o), t(this).attr("src", A)
}), e(), window.onscroll = function () {
e()
}
}
var r = {
coverColor: "#dfdfdf",
coverDiv: "",
showTime: 300,
offsetBottom: 0,
offsetTopm: 50,
onLoadBackEnd: function (t, o) {},
onLoadBackStart: function (t, o) {}
},
f = [],
s = t(window).height(),
l = (t(window).width(), t("img[data-lazy-src]")),
A = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
window.lazyLoadInit = d
}($);
对于源码还得深究啊
第二种(推荐用这种)
注意点:
1、必须给img设置默认高度,不然懒加载无效。
2、修改 img 里面属性 class=“lazy” data-original= “ ”
HTML结构
<!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>
<style>
img {
margin-bottom: 200px;
/* 注意:这个懒加载一定要给img默认高度 不然懒加载无效*/
height: 300px;
margin-right: 400px;
}
</style>
<body>
<img class="lazy" data-original="./images/P_000.jpg" alt="">
<img class="lazy" data-original="./images/P_001.jpg" alt="">
<img class="lazy" data-original="./images/P_002.jpg" alt="">
<img class="lazy" data-original="./images/P_003.jpg" alt="">
<img class="lazy" data-original="./images/P_004.jpg" alt="">
<img class="lazy" data-original="./images/P_005.jpg" alt="">
<img class="lazy" data-original="./images/P_006.jpg" alt="">
<img class="lazy" data-original="./images/P_007.jpg" alt="">
<img class="lazy" data-original="./images/P_008.jpg" alt="">
<img class="lazy" data-original="./images/P_009.jpg" alt="">
<img class="lazy" data-original="./images/P_010.jpg" alt="">
<img class="lazy" data-original="./images/P_011.jpg" alt="">
<img class="lazy" data-original="./images/P_012.jpg" alt="">
<img class="lazy" data-original="./images/P_013.jpg" alt="">
<img class="lazy" data-original="./images/P_014.jpg" alt="">
<img class="lazy" data-original="./images/P_015.jpg" alt="">
<img class="lazy" data-original="./images/P_016.jpg" alt="">
<img class="lazy" data-original="./images/P_017.jpg" alt="">
<img class="lazy" data-original="./images/P_018.jpg" alt="">
<img class="lazy" data-original="./images/P_019.jpg" alt="">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="./js/jquery.lazyload.js"></script>
<script>
// 为什么浏览器需要懒加载 :
// 1. 假设情况 : 页面之中有一千张图片,有一些是在显示区域内的,有一些是在显示区域外的;
// 因为浏览器加载图片是没有先后限制的,统一发起请求,谁先加载完就先渲染谁,资源分配随机, 会导致不好的用户体验。
// 2. 懒加载: 让浏览器把性能放在显示区域内去进行数据的加载;
// 使用懒加载插件即可;
$("img.lazy").lazyload({ effect: "fadeIn" });
// 注意事项 : 图片一定要设置默认高度否则懒加载无效;
</script>
</body>
</html>
jquery.lazyload.js 文件
/*
* Lazy Load - jQuery plugin for lazy loading images
*
* Copyright (c) 2007-2013 Mika Tuupola
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.appelsiini.net/projects/lazyload
*
* Version: 1.9.3
*
*/
(function ($, window, document, undefined) {
var $window = $(window);
$.fn.lazyload = function (options) {
var elements = this;
var $container;
var settings = {
threshold: 0,
failure_limit: 0,
event: "scroll",
effect: "show",
container: window,
data_attribute: "original",
skip_invisible: true,
appear: null,
load: null,
placeholder: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"
};
function update() {
var counter = 0;
elements.each(function () {
var $this = $(this);
if (settings.skip_invisible && !$this.is(":visible")) {
return;
}
if ($.abovethetop(this, settings) ||
$.leftofbegin(this, settings)) {
/* Nothing. */
} else if (!$.belowthefold(this, settings) &&
!$.rightoffold(this, settings)) {
$this.trigger("appear");
/* if we found an image we'll load, reset the counter */
counter = 0;
} else {
if (++counter > settings.failure_limit) {
return false;
}
}
});
}
if (options) {
/* Maintain BC for a couple of versions. */
if (undefined !== options.failurelimit) {
options.failure_limit = options.failurelimit;
delete options.failurelimit;
}
if (undefined !== options.effectspeed) {
options.effect_speed = options.effectspeed;
delete options.effectspeed;
}
$.extend(settings, options);
}
/* Cache container as jQuery as object. */
$container = (settings.container === undefined ||
settings.container === window) ? $window : $(settings.container);
/* Fire one scroll event per scroll. Not one scroll event per image. */
if (0 === settings.event.indexOf("scroll")) {
$container.bind(settings.event, function () {
return update();
});
}
this.each(function () {
var self = this;
var $self = $(self);
self.loaded = false;
/* If no src attribute given use data:uri. */
if ($self.attr("src") === undefined || $self.attr("src") === false) {
if ($self.is("img")) {
$self.attr("src", settings.placeholder);
}
}
/* When appear is triggered load original image. */
$self.one("appear", function () {
if (!this.loaded) {
if (settings.appear) {
var elements_left = elements.length;
settings.appear.call(self, elements_left, settings);
}
$("<img />")
.bind("load", function () {
var original = $self.attr("data-" + settings.data_attribute);
$self.hide();
if ($self.is("img")) {
$self.attr("src", original);
} else {
$self.css("background-image", "url('" + original + "')");
}
$self[settings.effect](settings.effect_speed);
self.loaded = true;
/* Remove image from array so it is not looped next time. */
var temp = $.grep(elements, function (element) {
return !element.loaded;
});
elements = $(temp);
if (settings.load) {
var elements_left = elements.length;
settings.load.call(self, elements_left, settings);
}
})
.attr("src", $self.attr("data-" + settings.data_attribute));
}
});
/* When wanted event is triggered load original image */
/* by triggering appear. */
if (0 !== settings.event.indexOf("scroll")) {
$self.bind(settings.event, function () {
if (!self.loaded) {
$self.trigger("appear");
}
});
}
});
/* Check if something appears when window is resized. */
$window.bind("resize", function () {
update();
});
/* With IOS5 force loading images when navigating with back button. */
/* Non optimal workaround. */
if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {
$window.bind("pageshow", function (event) {
if (event.originalEvent && event.originalEvent.persisted) {
elements.each(function () {
$(this).trigger("appear");
});
}
});
}
/* Force initial check if images should appear. */
$(document).ready(function () {
update();
});
return this;
};
/* Convenience methods in jQuery namespace. */
/* Use as $.belowthefold(element, {threshold : 100, container : window}) */
$.belowthefold = function (element, settings) {
var fold;
if (settings.container === undefined || settings.container === window) {
fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();
} else {
fold = $(settings.container).offset().top + $(settings.container).height();
}
return fold <= $(element).offset().top - settings.threshold;
};
$.rightoffold = function (element, settings) {
var fold;
if (settings.container === undefined || settings.container === window) {
fold = $window.width() + $window.scrollLeft();
} else {
fold = $(settings.container).offset().left + $(settings.container).width();
}
return fold <= $(element).offset().left - settings.threshold;
};
$.abovethetop = function (element, settings) {
var fold;
if (settings.container === undefined || settings.container === window) {
fold = $window.scrollTop();
} else {
fold = $(settings.container).offset().top;
}
return fold >= $(element).offset().top + settings.threshold + $(element).height();
};
$.leftofbegin = function (element, settings) {
var fold;
if (settings.container === undefined || settings.container === window) {
fold = $window.scrollLeft();
} else {
fold = $(settings.container).offset().left;
}
return fold >= $(element).offset().left + settings.threshold + $(element).width();
};
$.inviewport = function (element, settings) {
return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
!$.belowthefold(element, settings) && !$.abovethetop(element, settings);
};
/* Custom selectors for your convenience. */
/* Use as $("img:below-the-fold").something() or */
/* $("img").filter(":below-the-fold").something() which is faster */
$.extend($.expr[":"], {
"below-the-fold": function (a) {
return $.belowthefold(a, {
threshold: 0
});
},
"above-the-top": function (a) {
return !$.belowthefold(a, {
threshold: 0
});
},
"right-of-screen": function (a) {
return $.rightoffold(a, {
threshold: 0
});
},
"left-of-screen": function (a) {
return !$.rightoffold(a, {
threshold: 0
});
},
"in-viewport": function (a) {
return $.inviewport(a, {
threshold: 0
});
},
/* Maintain BC for couple of versions. */
"above-the-fold": function (a) {
return !$.belowthefold(a, {
threshold: 0
});
},
"right-of-fold": function (a) {
return $.rightoffold(a, {
threshold: 0
});
},
"left-of-fold": function (a) {
return !$.rightoffold(a, {
threshold: 0
});
}
});
})(jQuery, window, document);