相信不少小伙伴在工做中都会遇到图片请求数量过多,致使出现页面会出现卡顿的状况,在咱们前端开发工做中,页面的渲染速度是十分重要的。
谈到这,咱们都知道其中最大的一个问题就是图片加载速度
会拖累整个页面体验。不少页面,内容很丰富,页面很长,图片较多,好比说各类商城页面。这些页面图片数量多,并且比较大,少说百来K,多则上兆。有的时候没有必要一次性加载完。不然常会出现加载半张图片或是残缺,网速很差的有时候还会出现图片加载不出来等问题。
那么咱们可使用现有的技术,先显示可视区域
中的图片,再使剩余图片未显示的图片和滚动条事件
作交互,“滑到你,你再显示出来”,这也就是咱们常说的懒加载
,来咱们看一下关于懒加载的定义。前端
懒加载
(Load On Demand)是一种独特而又强大的数据获取
方法,它可以在用户滚动页面
的时候自动获取更多的数据,而新获得的数据不会影响原有数据的显示,同时最大程度上减小服务器端的资源耗用。git
关于懒加载的方式有不少种,在这里只会着重介绍其中两种,传统的懒加载方式
以及交叉观察者
这两种方式。github
传统的
懒加载
方式其实就是经过监听滚动轴的变化,去请求出如今可视区域的图片。数组
将页面中的
img
标签src
指向一张小图片或者src
为空,而后定义data-src
(这个属性能够自定义命名,我采用data-src
)属性指向真实的图片。
浏览器
<div class="box">
// 在这里咱们使用自定义属性data-src存储真实的图片地址
<img style="margin-top: 600px;" class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e26e2947?w=533&h=300&f=jpeg&s=44672"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e28ba479?w=500&h=463&f=jpeg&s=10435"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5b3c69c?w=579&h=300&f=jpeg&s=23132"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e60d6bc9?w=500&h=394&f=jpeg&s=27013"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5ac147c?w=500&h=313&f=jpeg&s=29734"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d1e5d0a8ef?w=428&h=600&f=jpeg&s=37727"
alt="">
<img class="img" src=""
data-src="https://user-gold-cdn.xitu.io/2019/9/7/16d0a7d2033996bc?w=500&h=325&f=jpeg&s=9951"
alt="">
</div>
复制代码
.box {
width: 800px;
height: 400px;
border: 1px solid;
overflow: auto;
}
.img {
width: 100px;
height: 100px;
border: 1px solid;
display: block;
margin: 40px auto;
}
复制代码
在这里咱们基本能够实现一个这样的界面bash
1.首先咱们先去获取父级元素以及子元素
const box = document.querySelector('.box');
const imgs = document.querySelectorAll('.img');
2.监听父级滚动轴变化
box.addEventListener('scroll', handleListenScroll);
3.实现监听函数
function handleListenScroll() {
//获取父级滚动轴距离顶部距离
var scrollTop = box.scrollTop;
//获取父级高度
var divHeight = box.clientHeight;
for (var i = 0; i < imgs.length; i++){
if (imgs[i].offsetTop < divHeight + scrollTop) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
这样一个简单的懒加载就实现了,咱们看下效果。
复制代码
若是直接将函数绑定在scroll事件上,当页面滚动时,函数会被高频触发,这很是影响浏览器的性能。服务器
所谓
节流
,就是当持续触发事件时,保证必定时间段内只调用一次事件处理函数。这里也许会有小伙伴说了,防抖
呢?先说一下防抖
的概念吧,当持续触发事件时,必定时间段内没有再触发事件,事件处理函数才会执行一次,若是设定的时间到来以前,又一次触发了事件,就从新开始延时。根据咱们的场景,显然在这里使用防抖
是不太合适的。app
box.addEventListener('scroll', throttle(handleListenScroll, 500));
//节流实现
function throttle(func, delay) {
var previous = 0;
return function () {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > delay) {
func.apply(context, args);
previous = now;
}
};
}
复制代码
小tip 在使用的时候咱们也能够给每一个图片一个默认图片,等图片出如今可视区域的时候进行一个替换。异步
交叉观察者
其实就是利用IntersectionObserver
接口 (从属于Intersection Observer API
) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport
)交叉状态的方法。祖先元素与视窗(viewport
)被称为根(root
)。函数
用通俗的话来说就是判断目标元素有没有和父级元素产生交叉行为,一张图说明一切,画的丑,请见谅~~
呃呃呃, IE几乎全军覆没,不过,有官方提供过的polyfill
,啥都不用怕,点这里。
属性 | 介绍 |
---|---|
root | 所监听对象的具体祖先元素(element)。若是未传入值或值为null,则默认使用顶级文档的视窗。 |
rootMargin | 计算交叉时添加到根(root)边界盒bounding box的矩形偏移量, 能够有效的缩小或扩大根的断定范围从而知足计算须要 |
thresholds | 一个包含阈值的列表, 按升序排列, 列表中的每一个阈值都是监听对象的交叉区域与边界区域的比率。 |
方法 | 介绍 |
---|---|
disconnect() | 使IntersectionObserver对象中止监听工做 |
observe() | 使IntersectionObserver开始监听一个目标元素。 |
takeRecords() | 返回全部观察目标的IntersectionObserverEntry对象数组。 |
unobserve() | 使IntersectionObserver中止监听特定目标元素。 |
1.新建一个IntersectionObserver
对象。
const observer = new IntersectionObserver(entries => {
// 发生交叉目标元素集合
console.log(entries);
}, option);
在这里callback会返回给咱们当前已监听而且发生了交叉的目标集合,咱们看一下具体信息。
复制代码
属性 | 介绍 |
---|---|
boundingClientRect | 空间信息 |
target | 目标元素 |
isIntersecting | 是否发生交叉 |
2.监听目标元素
const box = document.querySelector('.box');
const imgs = document.querySelectorAll('.img');
const observer = new IntersectionObserver(entries => {
// 发生交叉目标元素集合
entries.forEach(item => {
// 判断是否发生交叉
if (item.isIntersecting) {
// 替换目标元素Url
item.target.src = item.target.dataset.src;
// 取消监听此目标元素
observer.unobserve(item.target);
}
});
}, {
root: box, // 父级元素
rootMargin: '20px 0px 100px 0px' // 设置偏移 咱们能够设置在目标元素距离底部100px的时候发送请求
});
imgs.forEach(item => {
// 监听目标元素
observer.observe(item);
});
复制代码
以上就是使用
IntersectionObserver
实现懒加载的过程,是否是很简单呢,在这里咱们再也不须要去监听滚动条的变化,只须要根据返回给咱们的元素集合就能够实现。还要记住必须是子元素跟父元素发生交叉,是不能够去检查两个非父子关系的交叉的状况哦~~
综上 就是我对于懒加载一点小看法,也但愿将来咱们的页面更加流畅,so,先从懒加载开始吧~~。其实懒加载只是经过IntersectionObserver
实现的一点小功能,IntersectionObserver
还能够帮咱们实现吸顶
、触底
这些功能,感兴趣的小伙伴能够去试试哦。最后,文中若有错误,欢迎在评论区指正,若是这篇文章帮助到了你,欢迎点赞👍和关注,😀。