前言
这几天在面试时,面试官问我用过哪些vueUse中的工具函数或者说是hook,我说了useIntersectionObserver(用来判断元素是否进行可视区域的),useScroll(用来判断滚顶条下滑距离的),面试官问我明白这两个hook的原理吗,当时只是简单说了一下思路,现在使用原生js来实现一下。
useIntersectionObserver
这个hook的作用其实就是判断某元素是否进入了可视区域。
原理图奉上:
若认为:当图片的边缘进入可视区域时,就算该元素进入了可视区域,那么不难理解公式就是:
公式: offsetTop - scrollTop <= clientHeight
(这里的offsetTop、scrollTop、clientHeight指的都是目标元素的属性)
解释概念:
offsetTop:指的是元素距离网页页头的距离(不局限于当前页面)。
scrollTop:指的是滚动条滑动的距离。
clientHeight:指的是当前设备可视区域的高度。
代码实现
思路一:
<style>
body {
height: 3000px;
}
.box {
width: 100px;
height: 100px;
background-color: skyblue;
margin-top: 1500px;
}
</style>
// 获取目标元素
let box = document.querySelector('.box')
// 设备高度
let deviceHeight = document.documentElement.clientHeight
// 定义动态判断元素是否位于可视区域的方法
function isElementInVisible(){
let scrollTop = document.documentElement.scrollTop
let offsetTop = box.offsetTop
if(offsetTop - scrollTop <= deviceHeight){
console.log('进入了可视区域')
}else {
console.log('尚未进入可视区域')
}
}
window.onscroll = isElementInVisible
注意:如果单纯给scroll事件绑定回调可能导致严重的性能问题,因此一般交给scroll事件的回调应使用防抖做处理
思路二:
使用 Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
function isElementInVisible(){
let deviceHeight = document.documentElement.clientHeight
let domRect = box.getBoundingClientRect()
if(domRect.top <= domRect) {
console.log('进入了可视区域')
}else {
console.log('尚未进入可视区域')
}
}
window.onscroll = isElementInVisible
思路三:
使用js原生的IntersectionObserver。
MDN解释: IntersectionObserver 接口(从属于 Intersection Observer API)提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。
let intersectionObserver = new IntersectionObserver((entries) => {
if(entries[0].intersectionRatio <= 0) return
console.log("进入了可视区域")
})
intersectionObserver.observe(document.getElementsByClassName('box')[0])
useScroll
这个hook的作用就是获得滚动条的一些参数,如滚动条的下滑距离。
// 方法一
document.addEventListener('scroll',(e) => {
console.log(Math.floor(document.documentElement.scrollTop))
})
// 方法二
document.addEventListener('scroll',(e) => {
console.log(Math.floor(window.pageYOffset))
})
效果: