Intersection Observer API
是⼀种⽤于异步检查⽂档中元素与视⼝叠加程度的API。
1、可以将其⽤于检测图⽚是否已经进⼊视⼝,并根据需要进⾏相应的处理。 图片懒加载
2、 可以用于视口的 曝光加载
IntersectionObserverEntry
对象的属性
boundingClientRect
: 目标元素的边界矩形。intersectionRatio
: 目标元素与根元素(或视口)相交的比例,介于 0.0 和 1.0 之间。intersectionRect
: 目标元素与根元素(或视口)相交区域的矩形。isIntersecting
: 一个布尔值,指示目标元素是否与根元素(或视口)相交。rootBounds
: 根元素的边界矩形,如果根元素是视口则为视口的边界矩形。target
: 被观察的目标元素。time
: 这个交集改变发生的时间戳。
// 曝光加载
<template>
<div class="scroll-box" ref="scollbox" :style="'max-height:' + height">
<slot></slot>
<div ref="endBox" class="add-more">
{{ !end ? (isloading ? "加载中..." : "加载完成") : "没有更多了" }}
</div>
</div>
</template>
<script>
/**
* isloading 默认为 false,在元素曝光后执行加载 ,为 true时候为加载中,
* 每次加载过程中都会改变 isloading 为 true,加载完成后 外面设置 isloading = false
* end 默认为 false 可以加载更多, 为 true 时候注销监听
* @send 发起加载请求
*/
export default {
props: {
isloading: {
type: Boolean,
default: false,
},
height: {
type: String,
default: "270px",
},
end: {
type: Boolean,
default: false,
},
},
data() {
return {
observer: "",
};
},
watch: {
end(val) {
if (val) {
if (this.observer) {
this.observer.disconnect();
}
}
},
},
mounted() {
this.initScrollHandle();
},
methods: {
initScrollHandle() {
this.observer = new IntersectionObserver(
(changes) => {
const change = changes[0];
if (change.intersectionRatio > 0.1) {
// 曝光加载
this.starLoad();
}
},
{
root: this.$refs.scollbox,
threshold: 0.2,
}
);
// this.$refs.scollbox
if (!this.end) {
this.addObserve();
}
},
addObserve() {
const { observer } = this;
if (observer) {
observer.observe(this.$refs.endBox);
}
},
starLoad() {
if (!this.isloading) {
console.log("执行send");
this.$emit("send");
this.$emit("update:isloading", true); // 加载过程中为 false // 加载完成改为 ture 可以继续加载
}
},
},
};
</script>
<style lang="scss" scoped>
.scroll-box {
height: 270px;
overflow: hidden;
overflow-y: auto;
margin-bottom: 8px;
&::-webkit-scrollbar {
width: 15px;
height: 15px;
}
&::-webkit-scrollbar-thumb {
background-color: var(--color-on-light-600);
background-clip: content-box;
border: 4px solid transparent;
border-radius: 8px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: var(--color-on-light-700);
}
&::-webkit-scrollbar-track {
background-color: #fff;
box-shadow: inset;
}
}
.add-more {
text-align: center;
font-size: 12px;
color: #333;
}
</style>
图片懒加载
function lazyLoadImages(imgSelector) {
const images = document.querySelectorAll(imgSelector);
const config = {
rootMargin: '0px 0px 50px 0px',
threshold: 0
};
const observer = new IntersectionObserver(function(entries, self) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute('data-src');
img.src = src;
self.unobserve(img);
}
});
}, config);
images.forEach(img => {
observer.observe(img);
});
}
// 使用时,确保在文档加载完成后调用
document.addEventListener('DOMContentLoaded', function() {
lazyLoadImages('img[data-src]');
});