1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > JS实现图片延迟加载(图片懒加载)

JS实现图片延迟加载(图片懒加载)

时间:2021-07-26 03:55:33

相关推荐

JS实现图片延迟加载(图片懒加载)

1.为什么需要做图片的懒加载

=>第一次加载页面的时候,如果请求真实图片资源,会减缓页面的渲染速度,为了提高首次打开的体验度,我们最开始不加载真实的图片资源(比如大小很小的背景图片),只有当第一次页面整体都渲染完成后,页面中已经呈现出除图片以外的其它资源后,再去按需加载真实的图片资源渲染

=>进一步优化,最开始只加载首屏需要的图片,等到滚动条滚动的时候,再把当前屏幕中需要渲染的图片加载(避免不必要的资源加载)

2.解决步骤

1)给需要延迟加载的图片设置一个外层盒子,图片在这个盒子中

2)我们把图片的SRC设置为空,把后续需要请求的真实图片地址赋值给IMG的自定义属性

3)在最开始渲染的样式中

->给外层的盒子设置等待加载的背景LOGO(或者背景颜色,如果是背景图片,图片一定要非常的小,最好控制在5KB以内),让盒子起到一个占位的作用

->让所有的SRC为空的IMG默认是隐藏的

4)需要等到页面加载完成后(除图片资源,其它资源都加载完成了 window.onload),在JS中获取真实图片的地址,赋值给其SRC(此时才去加载真实的图片进行渲染)

代码实现:第一次加载页面

<head><style>/* img自带样式*/img:not([src]),img[src=""] {display: none}.lazyImgBox {box-sizing: border-box;width: 300px;height: 500px;background: url("images/default.gif") no-repeat center center #DDD;}.lazyImgBox img {width: 100%;height: 100%;}</style></head><body><div class="lazyImgBox"><img src="" alt="" data-image="images/1.jpg"></div><!-- IMPORT JS --><script>var lazyImgBox = document.querySelector('.lazyImgBox'),img = lazyImgBox.querySelector('img');window.onload = function () {// 获取IMG中的真实图片地址 DATA-IMAGE,赋值给它的SRClet trueSRC = img.getAttribute('data-image');img.src = trueSRC;img.removeAttribute('data-image');};// 定时器方法 // setTimeout(function () {// // 定时器是异步的,它能够触发执行的条件:不仅是到达时间了,而且是主线程已经加载完成了(所以可以用它代替window.onload)//// // 进一步优化:在IE浏览器中,如果我们加载的图片不存在,在图片区域不展示任何图片,会展示一个“×”,不太好看,所以我们在赋值SRC之前,一般先自己校验一下地址的真实性// var dataImage = img.getAttribute('data-image');// var tempImg = new Image; //=>创建一个临时的图片对象(它不会增加到页面中,它就是用来检测地址的合法性的)// tempImg.src = dataImage;// tempImg.onload = function () {// // 当前地址是正确的(tempImg.onload代表图片能正常加载出来)// img.src = dataImage;// };// img.removeAttribute('data-image');// tempImg = null;// }, 1000);</script>

代码实现:等到滚动条滚动的时候,再把当前屏幕中需要渲染的图片加载

<head><style>.lazyImgBox {box-sizing: border-box;margin: 1000px 0;width: 300px;height: 500px;background: url("images/default.gif") no-repeat center center #DDD;}.lazyImgBox img {width: 100%;height: 100%;/* 为了后期图片显示有动画效果 */opacity: 0;transition: opacity .3s ease 0s;}</style></head><body><div class="lazyImgBox"><img src="" alt="" data-image="images/1.jpg"></div><!-- IMPORT JS --><script src="js/utils.js"></script><script>let lazyImgBox = document.querySelector('.lazyImgBox'),img = lazyImgBox.querySelector('img'),HTML = document.documentElement;// B:图片所在盒子底边距离BODY顶端的距离// cH:浏览器可视窗口一屏幕的高度// A:浏览器底边框距离BODY顶端的距离let B = utils.offset(lazyImgBox).top + lazyImgBox.offsetHeight,cH = HTML.clientHeight,A = 0;window.onscroll = function () {if (img.isLoad) return; //=>已经处理过了,则其余的都不在处理A = cH + HTML.scrollTop;// 延迟加载的条件:图片完全出现在可视窗口中(B<=A)if (B <= A) {// 问题:当我们把图片加载出来(或者地址不存在没加载,但是也处理了),但是对着浏览器继续滚动,B<=A的条件一直成立,会一直触发延迟加载操作 =>在第一次处理完成后,后续即使在符合条件我们也不处理了lazy();}};// 进行图片延迟加载function lazy() {let dataImage = img.getAttribute("data-image"),tempImage = new Image;tempImage.src = dataImage;tempImage.onload = () => {img.src = dataImage;// 动画:改变他的OPCITY样式即可// img.offsetHeight; //=>先让上面显示的样式渲染(触发一次回流),再让下面透明度的样式改变,这样就能看到动画效果了utils.css(img, 'opacity', 1);};img.removeAttribute('data-image');tempImage = null;img.isLoad = true; //=>不论成功还是失败,都标识一下当前图片我已经处理过了}

用到的工具库方法:

var utils = (function () {function getCss(element, attr) {// 优化:如果我们获取的结果符合 "数字+单位" 100px 的格式,我们默认就把单位去掉,变为纯数字;// 如果获取的是 “纯数字的字符串”,‘1’ 我们也把其转换为数字;// 如果是组合值或者非数字的 auto ,则不进行任何的处理;let value = window.getComputedStyle(element)[attr],reg = /^\d+(px|rem|em)?$/i;if (reg.test(value)) {value = parseFloat(value);}return value;}function setCss(element, attr, value) {// 优化:如果传递的是opacity,在IE低版本中用的filter设置样式if (attr === "opacity") {element['style']['opacity'] = value;element['style']['filter'] = `alpha(opacity=${value*100})`;return;}// 优化:对于某些特定样式(例如:width/height/margin/padding/marginTop.../paddingTop.../left/top/bottom/right...)如果传递的value没有带单位的(纯数字)我们手动默认给他加上PX单位let reg = /^(width|height|margin|padding)?(top|left|bottom|right)?$/i;if (reg.test(attr)) {// 只有人家value没有传单位,我们才自己加单位(只有传递的是有效数字,我们才设置单位)if (!isNaN(value)) {value += 'px';}}element['style'][attr] = value;}function setGroupCss(element, options) {// 循环传递的样式对象,分别调取setCss设置样式即可for (let key in options) {if (!options.hasOwnProperty(key)) break;setCss(element, key, options[key]);}}//修改或者获取元素的样式function css(element) {// 1.如果传递的是三个参数则为单一设置样式// 2.如果传递的是两个参数// 第二个参数是个对象:则为批量设置样式// 第二个参数是个字符串:则为获取样式let len = arguments.length,attr = arguments[1],value = arguments[2];if (len >= 3) {// 单一设置样式setCss(element, attr, value);return;}if (attr !== null && typeof attr === "object") {// 批量设置setGroupCss(element, attr);return;}// 获取样式return getCss(element, attr);}function offset(element) {// 1.首先获取当前元素的父参照物和其距离父参照物的偏移let parent = element.offsetParent,top = element.offsetTop,left = element.offsetLeft;// 2.循环依次向上查找父参照物(一直到找不到为止)while (parent) {// 加上父参照物的边框(非IE8浏览器中才加)if (!/MSIE 8/.test(navigator.userAgent)) {left += parent.clientLeft;top += parent.clientTop;}// 加上父参照物的偏移值left += parent.offsetLeft;top += parent.offsetTop;// 继续向上查找parent = parent.offsetParent;}// 3.把查找的结果返回return {// top:toptop,left};}return {css,offset}})();

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。