最近vue3在开发一个页面懒加载组件,使用到的核心API就是IntersectionObserver,虽然之前也了解用过,但是还是不够理解,本文就用于记录自己的学习理解过程
核心逻辑
- IntersectionObserver中的callback触发
- 当IntersectionObserver指定的root窗口元素 与 observe入参所指向的监听dom元素之间的intersctionRadio大于等于IntersectionObserver中指定的threshold时,会触发callback
- intersectionRadion = 被监听元素在视图中出现的高度 / 被监听元素的总高度
intersectionRect
与boundingClientRect
的比例值,返回的值并不总是恰好符合公式,会存在少许误差
case 1 不触发callback
case 2 触发callback
2. 设置threshold需要注意,能触发callback的最大threshold并不总是为1
-
- 当被监听元素的大小大于窗口元素,最大threshold = 窗口元素的高 / 被监听元素的总高
用法
- 创建IntersectionObserver实例intersectionObserverInstance
- 参数
- callback(entries, observer)
- options
- root
- rootMargin
- threshold
- 参数
- 通过intersectionObserverInstance.observe(dom)对希望监听的dom对象与窗口元素交叉程度进行监听
// vue3 demo
<template>
<div ref="wrap">
<slot v-if="!isShowComp" name="skelton"></slot>
<slot v-if="!isShowComp" name="loading">加载中</slot>
<slot v-else></slot>
</div>
</template>
<script setup>
import {onMounted, ref, watch} from 'vue';
let isShowComp = ref(false);
const wrap = ref(null);
const props = defineProps({
root: {
type: Object,
default(rawProp) {
return rawProp || null
}
},
threshold: {
type: [Number, Array],
default: 0.58
}
})
const initObsever = () => {
return new IntersectionObserver((entries, observer) => {
console.log(entries[0])
entries.forEach(el => {
if (props.threshold instanceof Array) {
setTimeout(() => {
isShowComp.value = true;
observer.disconnect();
}, 5000);
} else if (el.intersectionRatio >= props.threshold) {
setTimeout(() => {
isShowComp.value = true;
observer.disconnect();
}, 5000);
}
})
}, {
root: props.root,
threshold: props.threshold
});
}
let observer = initObsever();
onMounted(() => {
observer.observe(wrap.value)
})
</script>
<style lang="scss" scoped></style>