整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端开发,原生 JS 实现最简单的图片懒加载


加载


什么是懒加载

懒加载其实就是延迟加载,是一种对网页性能优化可方式,比如当访问一个页面的时候,优先显示可视区域的图片而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源。

什么时候用懒加载

当页面中需要一次性载入很多图片的时候,往往都是需要用懒加载的。

懒加载原理

我们都知道HTML中的 <img>标签是代表文档中的一个图像。。说了个废话。。

<img>标签有一个属性是 src,用来表示图像的URL,当这个属性的值不为空时,浏览器就会根据这个值发送请求。如果没有 src属性,就不会发送请求。

嗯?貌似这点可以利用一下?

我先不设置 src,需要的时候再设置?

nice,就是这样。

我们先不给 <img>设置 src,把图片真正的URL放在另一个属性 data-src中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到 src中。

实现


HTML结构

<div class="container">
 <div class="img-area">
   <img class="my-photo" alt="loading" data-src="./img/img1.png">
 </div>
 <div class="img-area">
   <img class="my-photo" alt="loading" data-src="./img/img2.png">
 </div>
 <div class="img-area">
   <img class="my-photo" alt="loading" data-src="./img/img3.png">
 </div>
 <div class="img-area">
   <img class="my-photo" alt="loading" data-src="./img/img4.png">
 </div>
 <div class="img-area">
   <img class="my-photo" alt="loading" data-src="./img/img5.png">
 </div>
</div>

仔细观察一下, <img>标签此时是没有 src属性的,只有 alt和 data-src属性。

alt 属性是一个必需的属性,它规定在图像无法显示时的替代文本。 data-* 全局属性:构成一类名称为自定义数据属性的属性,可以通过 HTMLElement.dataset来访问。

如何判断元素是否在可视区域

方法一

网上看到好多这种方法,稍微记录一下。

  1. 通过 document.documentElement.clientHeight获取屏幕可视窗口高度
  2. 通过 document.documentElement.scrollTop获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离
  3. 通过 element.offsetTop获取元素相对于文档顶部的距离

然后判断②-③<①是否成立,如果成立,元素就在可视区域内。

方法二(推荐)

通过 getBoundingClientRect()方法来获取元素的大小以及位置,MDN上是这样描述的:

The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport.

这个方法返回一个名为 ClientRect的 DOMRect对象,包含了 top、 right、 botton、 left、 width、 height这些值。

MDN上有这样一张图:

可以看出返回的元素位置是相对于左上角而言的,而不是边距。

我们思考一下,什么情况下图片进入可视区域。

假设 constbound=el.getBoundingClientRect();来表示图片到可视区域顶部距离; 并设 constclientHeight=window.innerHeight;来表示可视区域的高度。

随着滚动条的向下滚动, bound.top会越来越小,也就是图片到可视区域顶部的距离越来越小,当 bound.top===clientHeight时,图片的上沿应该是位于可视区域下沿的位置的临界点,再滚动一点点,图片就会进入可视区域。

也就是说,在 bound.top<=clientHeight时,图片是在可视区域内的。

我们这样判断:

function isInSight(el) {
 const bound = el.getBoundingClientRect();
 const clientHeight = window.innerHeight;
 //如果只考虑向下滚动加载
 //const clientWidth = window.innerWeight;
 return bound.top <= clientHeight + 100;
}

这里有个+100是为了提前加载。

加载图片

页面打开时需要对所有图片进行检查,是否在可视区域内,如果是就加载。

function checkImgs() {
 const imgs = document.querySelectorAll('.my-photo');
 Array.from(imgs).forEach(el => {
   if (isInSight(el)) {
     loadImg(el);
   }
 })
}

function loadImg(el) {
 if (!el.src) {
   const source = el.dataset.src;
   el.src = source;
 }
}

这里应该是有一个优化的地方,设一个标识符标识已经加载图片的index,当滚动条滚动时就不需要遍历所有的图片,只需要遍历未加载的图片即可。

函数节流

在类似于滚动条滚动等频繁的DOM操作时,总会提到“函数节流、函数去抖”。

所谓的函数节流,也就是让一个函数不要执行的太频繁,减少一些过快的调用来节流。

基本步骤:

  1. 获取第一次触发事件的时间戳
  2. 获取第二次触发事件的时间戳
  3. 时间差如果大于某个阈值就执行事件,然后重置第一个时间
function throttle(fn, mustRun = 500) {
 const timer = null;
 let previous = null;
 return function() {
   const now = new Date();
   const context = this;
   const args = arguments;
   if (!previous){
     previous = now;
   }
   const remaining = now - previous;
   if (mustRun && remaining >= mustRun) {
     fn.apply(context, args);
     previous = now;
   }
 }
}

这里的 mustRun就是调用函数的时间间隔,无论多么频繁的调用 fn,只有 remaining>=mustRun时 fn才能被执行。

实验


页面打开时

可以看出此时仅仅是加载了img1和img2,其它的img都没发送请求,看看此时的浏览器

第一张图片是完整的呈现了,第二张图片刚进入可视区域,后面的就看不到了~

页面滚动时

当我向下滚动,此时浏览器是这样

此时第二张图片完全显示了,而第三张图片显示了一点点,这时候我们看看请求情况

img3的请求发出来,而后面的请求还是没发出~

全部载入时

当滚动条滚到最底下时,全部请求都应该是发出的,如图

更新


方法三 IntersectionObserver

经大佬提醒,发现了这个方法

先附上链接:

jjc大大:

https://github.com/justjavac/the-front-end-knowledge-you-may-dont-know/issues/10

阮一峰大大:

http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html

API Sketch for Intersection Observers:

https://github.com/WICG/IntersectionObserver

IntersectionObserver可以自动观察元素是否在视口内。

var io = new IntersectionObserver(callback, option);
// 开始观察
io.observe(document.getElementById('example'));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();

callback的参数是一个数组,每个数组都是一个 IntersectionObserverEntry对象,包括以下属性:

属性描述time可见性发生变化的时间,单位为毫秒rootBounds与getBoundingClientRect()方法的返回值一样boundingClientRect目标元素的矩形区域的信息intersectionRect目标元素与视口(或根元素)的交叉区域的信息intersectionRatio目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0target被观察的目标元素,是一个 DOM 节点对象

我们需要用到 intersectionRatio来判断是否在可视区域内,当 intersectionRatio>0&&intersectionRatio<=1即在可视区域内。

代码

function checkImgs() {
 const imgs = Array.from(document.querySelectorAll(".my-photo"));
 imgs.forEach(item => io.observe(item));
}

function loadImg(el) {
 if (!el.src) {
   const source = el.dataset.src;
   el.src = source;
 }
}

const io = new IntersectionObserver(ioes => {
 ioes.forEach(ioe => {
   const el = ioe.target;
   const intersectionRatio = ioe.intersectionRatio;
   if (intersectionRatio > 0 && intersectionRatio <= 1) {
     loadImg(el);
   }
   el.onload = el.onerror = () => io.unobserve(el);
 });
});

源自:segmentfault

声明:文章著作权归作者所有,如有侵权,请联系小编删除。

我们进入到某个页面的时候,会有许多的图片,有些图片可能在下面,当我们点进页面但没有滑动全部展示时,其实下面的图片是没有作用的,这个时候如果说加载了也相当于白加载,而且还降低了网页的加载速度。滚动加载就是不需要展示的图片可以先不展示,滚动到指定位置的时候再加载;今天跟大家分享二种方式,一是滚动条到底部时去加载对应的数据,二是使用懒加载;

实现效果图

一、怎么实现滚动条到底部时去加载?

实现原理以及代码展示:

1)先请求第一页的数据

$.ajax({

type:'get', //请求类型

url:'http://127.0.0.1:8088/ list?page =1', //接口文档

dataType:'json',//返回值类型

//data:data,

success:function(data){

$.each(data,function(index,item){ //index 索引 item 当前元素

$(".index-main ul").append('<li class="lists">'+

'<img src="'+item. img_url+'" width="150" height="150">'+

'<label>'+

'<b class="discount">'+item. uprice+'</b>'+

'<span class="price-text">'+item. price+'</span> '+

'</label> '+

'</li>')

});

},

error:function(error){

console.log(error)

}

});

2)当滚动条移至底部时触发请求下一页的数据

$(window).scroll(function(){

var scrollTop = $(this).scrollTop(); //滚动条距离顶部的高度

var scrollHeight = $(document).height(); //当前页面的总高度

var clientHeight = $(this).height(); //当前可视的页面高度

if(scrollTop + clientHeight >= scrollHeight){ //距离顶部+当前高度 >=页面总高度 即滚动条到达底部

//再请求对应的数据

});

这样就可以实现鼠标移至底部加载下一页的数据~~~

二、懒加载

1、为什么要使用懒加载

懒加载就是只有滚动到可视区域时才加载当前的图片,也就是说不是一次性加载所有的图片,从而在一程度减少服务端的请求及带宽;

2、懒加载的优点:

提高前端性能,图片在需要的时候才加载,减轻服务的负担,提高页面的加载速度,能够减少带宽

3、实现原理

图片的加载是由src的值引起的,当对src赋值时浏览器会请求图片资源,基于这个,可以利用html5的属性data-xxx来保存图片的路径,当我们需要加载图片的时候才将data-xxx的值赋予src,就能实现图片的按需加载,也就是懒加载了;

懒加载的方法有很多,这里推荐使用jquery图片延迟加载jquery.lazyload

1)使用方法

引用jquery和jquery.lazyload.js到你的页面

<script src="js/jquery-1.11.1.min.js"></script>

<script src="js/jquery.lazyload.js"></script>

2)html图片调用方法

为图片加入样式lazy 图片路径引用方法用data-original

1. 将图片路径写入data-original属性

<img data-original="img/1.jpg" />

2. 选择所有要lazyload的图片(img.lazy),执行lazyload();

$("img").lazyload();

3、常用方法设置

1)提前加载——Threshold

lazyload默认是当滚动到该图片位置时,加载该图片。但是可以通过设置Threshold参数来实现滚到距离其xx px时就加载。

$("img.lazy").lazyload({

threshold :20

});

2)设定效果——Effects

插件默认的加载效果是 show() ,你可以使用任何你想要的效果。下面的代码使用了 fadeIn()

$("img.lazy").lazyload({

effect : "fadeIn"

});

4、当前实例的具体代码如下:

//按需加载

$.ajax({

type:'get', //请求类型get post put delete

url:'http://127.0.0.1:8088/ list’, //接口文档

dataType:'json',//返回值类型

//data:data,

success:function(data){

$.each(data,function(index,item){

$(".index-main ul").append('<li class="lists">'+

'<img data-original="'+item.product_img_url+'" width="150" height="150">'+

'<label>'+

'<b class="discount">'+item.product_uprice+'</b>'+

'<span class="price-text">'+item.product_price+'</span> '+

'</label> '+

'</li>')

});

//懒加载

$(".index-main ul img").lazyload({

effect:'fadeIn' //淡入效果

})

},

error:function(error){

console.log(error)

}

});

注:如果想添加加载动画

转发+关注我吧,每天更新web前端干货知识,原创需要大家的支持,你们的支持是我更新最大的动力!

页跨屏幕自适配已经成为网站的不二之选,跨屏幕适配是帮助传统网站快速抓住移动互联网这根稻草的有效解决方案,切图公司首个推出网页跨屏幕适配项目:跨无忧。并且揭露技术上网页适配的实现原理。

允许网页宽度自动调整

“自适应网页设计”到底是怎么做到的?其实并不难。跨无忧(www.Kuawuyou.com)为您剖析网页跨屏幕适配的技术实现原理:

首先,在网页代码的头部,加入一行viewport元标签。

viewport是网页默认的宽度和高度,上面这行代码的意思是,网页宽度默认等于屏幕宽度(width=device-width),原始缩放比例(initial-scale=1)为1.0,即网页初始大小占屏幕面积的100%。

所有主流浏览器都支持这个设置,包括IE9。对于那些老式浏览器(主要是IE6、7、8),需要使用css3-mediaqueries.js。

三、不使用绝对宽度

由于网页会根据屏幕宽度调整布局,所以不能使用绝对宽度的布局,也不能使用具有绝对宽度的元素。这一条非常重要。

具体说,CSS代码不能指定像素宽度:

width:xxxpx;

只能指定百分比宽度:

width:xx%;

或者

width:auto;

四、相对大小的字体

字体也不能使用绝对大小(px),而只能使用相对大小(em)。

body{

font:normal100%Helvetica,Arial,sans-serif;

}

上面的代码指定,字体大小是页面默认大小的100%,即16像素。

h1{

font-size:1.5em;

}

然后,h1的大小是默认大小的1.5倍,即24像素(24/16=1.5)。

small{

font-size:0.875em;

}

small元素的大小是默认大小的0.875倍,即14像素(14/16=0.875)。

五、流动布局(fluidgrid)

“流动布局”的含义是,各个区块的位置都是浮动的,不是固定不变的。

.main{

float:right;

width:70%;

}

.leftBar{

float:left;

width:25%;

}

float的好处是,如果宽度太小,放不下两个元素,后面的元素会自动滚动到前面元素的下方,不会在水平方向overflow(溢出),避免了水平滚动条的出现。

另外,绝对定位(position:absolute)的使用,也要非常小心。

六、选择加载CSS

“自适应网页设计”的核心,就是CSS3引入的MediaQuery模块。

它的意思就是,自动探测屏幕宽度,然后加载相应的CSS文件。

media=”screenand(max-device-width:400px)”

href=”tinyScreen.css”/>

上面的代码意思是,如果屏幕宽度小于400像素(max-device-width:400px),就加载tinyScreen.css文件。

media=”screenand(min-width:400px)and(max-device-width:600px)”

href=”smallScreen.css”/>

如果屏幕宽度在400像素到600像素之间,则加载smallScreen.css文件。

除了用html标签加载CSS文件,还可以在现有CSS文件中加载。

七、CSS的@media规则

同一个CSS文件中,也可以根据不同的屏幕分辨率,选择应用不同的CSS规则。

@mediascreenand(max-device-width:400px){

.column{

float:none;

width:auto;

}

#sidebar{

display:none;

}

}

上面的代码意思是,如果屏幕宽度小于400像素,则column块取消浮动(float:none)、宽度自动调节(width:auto),sidebar块不显示(display:none)。

八、图片的自适应(fluidimage)

除了布局和文本,”自适应网页设计”还必须实现图片的自动缩放。

这只要一行CSS代码:

img{max-width:100%;}

这行代码对于大多数嵌入网页的视频也有效,所以可以写成:

img,object{max-width:100%;}

老版本的IE不支持max-width,所以只好写成:

img{width:100%;}

此外,windows平台缩放图片时,可能出现图像失真现象。这时,可以尝试使用IE的专有命令:

img{-ms-interpolation-mode:bicubic;}

或者,EthanMarcotte的imgSizer.js。

addLoadEvent(function(){

varimgs=document.getElementById(“content”).getElementsByTagName(“img”);

imgSizer.collate(imgs);

});

最好还是做适配分辨率的图片。有很多方法可以做到同样效果,服务器端和客户端都可以实现。

关注切图网公众微信:qietuwang