需求:点击“回到顶部”按钮,返回H5页面的顶部。
1. 思路剖析
- 具体交互:滚动页面,当 区域A 进入了视口(viewport),即用户可见范围,则显示“回到顶部”按钮,否则,隐藏“回到顶部”按钮。
- 传统思路:监听滚动事件,频繁调用 Element.getBoundingClientRect() 方法以获取区域A的边界信息。但事件监听和调用 Element.getBoundingClientRect() 都是在主线程上运行,频繁触发、调用可能会造成性能问题。
- 新思路:联想到 IntersectionObserver API,它可用于相交检测,即检测一个元素是否可见或者两个元素是否相交。
2. 关于 IntersectionObserver API
- Intersection Observer API 会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时(或者 viewport),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行。
- 适用的业务场景:图片懒加载、内容无限滚动、在用户看见某个区域时执行任务或播放动画等。
3. 代码实战
/**
* @description: 点击“回到顶部”按钮,滚动至页面顶部
* @param {string} scrollToTopBtnElId “回到顶部”按钮元素ID
* @param {string} targetElId 目标元素ID,监控该目标是否进入当前屏幕,若是,显示按钮
*/
export function useScrollToTop (scrollToTopBtnElId: string, targetElId: string): void
{
// “回到顶部”按钮元素
const scrollToTopBtn = document.getElementById(scrollToTopBtnElId) as HTMLElement;
// 目标元素
const target = document.getElementById(targetElId) as HTMLElement;
// 滚动至页面顶部
const scrollToTop = () =>
{
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (scrollTop > 0)
{
window.scrollTo(0, 0);
}
};
// 观察器的回调函数
function callback (entries: any, observer: any)
{
// entries 保存被观察的对象,一个观察器可观察多个 DOM 节点
entries.forEach((entry: any) =>
{
// 判断当前元素是否可见
if (entry.isIntersecting)
{
// 显示“回到顶部”按钮
scrollToTopBtn.classList.add('show-btn');
}
else
{
// 隐藏“回到顶部”按钮
scrollToTopBtn.classList.remove('show-btn');
}
});
}
// 初始化一个观察器实例
const observer = new IntersectionObserver(callback);
if (target)
{
// 开始观察
observer.observe(target);
}
if (scrollToTopBtn)
{
// 给“回到顶部”按钮元素绑定点击事件
scrollToTopBtn.addEventListener('click', scrollToTop);
}
}