常见的懒加载方案
这个方案是借助滚动距离来判断的,获取document.documentElement的scrollTop与需要懒加载的图片标签的offsetTop进行比较,看图片是否进入可视区域,从而实现图片加载。
代码如下:
// 封装一个获取图片到顶部的距离
function getTop(elm){
let tempTop = elm.offsetTop;
//如果包裹img的父元素离顶部也有距离,那么也要把它加上
while(elm = elm.offsetParent) { //注意这儿offsetParent返回的是元素不是数值,同时这儿是赋值语句
tempTop += elm.offsetTop;
}
return tempTop;
}
function lazyLoad(imgs){
//获取可视区域高度
let viewHeight = document.documentElement.clientHeight || window.innerHeight;
//获取滚动高度
let scrollTopVal = document.documentElement.scrollTop || document.body.scrollTop;
for(var i = 0; i < imgs.length; i++){
if((viewHeight + scrollTopVal) > getTop(imgs[i])){
imgs[i].src = imgs[i].getAttribute('data-src')
}
}
}
// 使用
// 给你需要懒加载的图片设置一个类名'lazy-load'
let imgs = document.querySelectorAll('.lazy-load');
lazyLoad(imgs);
// 进行滚动监听
window.onscroll = function() {
lazyLoad(imgList);
}
使用交叉观察者实现懒加载
浏览器自带的API IntersectionObserver进行检测,十分方便
先贴上代码实现:
// 给你需要懒加载的图片设置一个类名'lazy-load'
let imgs = document.querySelectorAll('.lazy-load');
// 实例化一个交叉观察者对象
let obsever = new IntersectionObserver((entries) => {
entries.forEach((item, index, arrSelf) => {
// 判断检测的对象是否进入可视窗口
if(item.isIntersecting) {
// 进入后进行图片地址赋值
item.target.src = item.target.dataset.src;
// 实现图片加载后不在进行检测
obsever.unobserve(item.target);
}
});
});
// 注册观察需要懒加载的img
imgs.forEach((item) => {
obsever.observe(item);
});
IntersectionObserver
用法
new IntersectionObserver(callback, options);
- callback 是一个回调函数,接受一个参数,返回当前已监听并且发生了交叉的目标集合。
- options 配置参数,可选,是一个对象。
new IntersectionObserver((entries) => {
}, {
// options参数
});
entries当前已监听并且发生了交叉的目标集合,我们可以把它用来循环,entres的打印结果如下:

参数表,对于entries这个集合里面的每个对象都有如下常用的参数:
| 属性 | 说明 |
| - | - | - |
| boundingClientReact | 元素的空间信息,就是位置信息这些个 |
| intersctionRatio | 元素可见区域的占比 |
| isInterscting | 判断元素是否交叉,也就是元素在可视区是否可见了 |
| target | 目标节点,跟我们使用事件的event.target效果一样 |
| 属性 | 说明 |
| - | - | - |
| root | 指定父元素,默认为视窗 |
| rootMargin | 触发交叉的偏移值,默认为"0px 0px 0px 0px"。(上左下右,正数为向外扩散,负数则向内收缩) |
- IntersectionObserver的实例对象的常用方法
| 名称 | 说明 | 参数 |
| - | - | - | - |
| observe | 开始监听一个目标元素 | DOM节点 |
| unobserve | 停止监听一个目标元素 | DOM节点 |
| takeRecords | 返回所有监听的目标元素集合 | |
| disconnect | 停止监听所有元素 | |
封装一个支持多浏览器的懒加载方案
IntersectionObserve这个API用起来确实方便,但是还是有一部分浏览器不支持,所以需要封装判断下。
function getTop(elm){
let tempTop = elm.offsetTop;
//如果包裹img的父元素离顶部也有距离,那么也要把它加上
while(elm = elm.offsetParent) { //注意这儿offsetParent返回的是元素不是数值,同时这儿是赋值语句
tempTop += elm.offsetTop;
}
return tempTop;
}
function lazyLoad(imgs){
//获取可视区域高度
let viewHeight = document.documentElement.clientHeight;
//获取滚动高度
let scrollTopVal = document.documentElement.scrollTop || document.body.scrollTop;
console.log(viewHeight, scrollTopVal)
for(var i = 0; i < imgs.length; i++){
if((viewHeight + scrollTopVal) > getTop(imgs[i])){
imgs[i].src = imgs[i].getAttribute('data-src')
}
}
}
function useIntersectionObserve(imgList) {
let obsever = new IntersectionObserver((entries) => {
entries.forEach((item, index, arrSelf) => {
console.log(entries)
if(item.isIntersecting) {
item.target.src = item.target.dataset.src;
obsever.unobserve(item.target);
}
});
});
imgList.forEach((item) => {
obsever.observe(item);
});
}
export default {
// 这两个个方案要求img标签有默认的高度,不然当一个页面出来就展示图片的情况下会一下展示很多图片,
// 所以在使用懒加载方案时给img加默认高度
// 单独使用普通懒加载方案
lazyloadDefault(selector) {
let imgList = document.querySelectorAll(selector);
lazyLoad(imgList);
window.onscroll = function() {
lazyLoad(imgList);
}
},
// 单独使用IntersectionObserve
lazyLoadIntersectionObserver(selector) {
let imgList = document.querySelectorAll(selector);
let obsever = new IntersectionObserver((entries) => {
entries.forEach((item, index, arrSelf) => {
console.log(entries)
if(item.isIntersecting) {
item.target.src = item.target.dataset.src;
obsever.unobserve(item.target);
}
});
});
imgList.forEach((item) => {
obsever.observe(item);
});
},
// 多浏览器适配方案
lazyLoadPolyfill(selector) {
let imgList = document.querySelectorAll(selector);
if(!window.IntersectionObserver) {
lazyLoad(imgList);
window.onscroll = function() {
lazyLoad(imgList);
}
}else {
useIntersectionObserve(imgList)
}
}
}
常见的懒加载方案
这个方案是借助滚动距离来判断的,获取document.documentElement的scrollTop与需要懒加载的图片标签的offsetTop进行比较,看图片是否进入可视区域,从而实现图片加载。
代码如下:
使用交叉观察者实现懒加载
浏览器自带的API IntersectionObserver进行检测,十分方便
先贴上代码实现:
IntersectionObserver
用法
entries当前已监听并且发生了交叉的目标集合,我们可以把它用来循环,entres的打印结果如下:
参数表,对于entries这个集合里面的每个对象都有如下常用的参数:
| 属性 | 说明 |
| - | - | - |
| boundingClientReact | 元素的空间信息,就是位置信息这些个 |
| intersctionRatio | 元素可见区域的占比 |
| isInterscting | 判断元素是否交叉,也就是元素在可视区是否可见了 |
| target | 目标节点,跟我们使用事件的event.target效果一样 |
| 属性 | 说明 |
| - | - | - |
| root | 指定父元素,默认为视窗 |
| rootMargin | 触发交叉的偏移值,默认为"0px 0px 0px 0px"。(上左下右,正数为向外扩散,负数则向内收缩) |
| 名称 | 说明 | 参数 |
| - | - | - | - |
| observe | 开始监听一个目标元素 | DOM节点 |
| unobserve | 停止监听一个目标元素 | DOM节点 |
| takeRecords | 返回所有监听的目标元素集合 | |
| disconnect | 停止监听所有元素 | |
封装一个支持多浏览器的懒加载方案
IntersectionObserve这个API用起来确实方便,但是还是有一部分浏览器不支持,所以需要封装判断下。