且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

IntersectionObserver 实用方向

更新时间:2022-08-13 10:37:50

上一篇文章讲了在 js 中如何实现图片懒加载,这一篇则讲解,如何实现滑动到底部加载更多。
跟图片懒加载一样,滑动到底部加载更多,一般传统方式是监听 scroll 事件,现在有更简单的方式为 IntersectionObserver

传统方式(scroll)

通过监听滚动容器的 scroll 事件,每次滑动后,判断是否已经滑动到了底部,如果已经滑动到了底部,则触发加载事件。

let timer = -1 // 函数防抖
let $scroll = document.querySelector('#scroll') // 滑动的容器

// 为滑动的容器添加 scroll 事件
$scroll.addEventListener('scroll', function () {
  clearTimeout(timer)
  timer = setTimeout(() => {
    // 滚动所在容器的可视高度
    let height = $scroll.getBoundingClientRect().height
    let top = $scroll.scrollTop // 滚动的距离
    let scrollHeight = $scroll.scrollHeight // 滚动容器的实际高度
    if (scrollHeight - top - height <= 60) {
      // 处于滑动临界值内,处理加载更多
      loadmore() // 加载更多
    }
  }, 150) // 避免过于频繁,防抖
})

跟图片懒加载一样,由于频繁的触发 scroll 的性能影响问题,使用 IntersectionObserver 能够解决这个问题。

IntersectionObserver

要使用 IntersectionObserver 来判断是否滑动到底部,我们就需要在列表的底部,添加一个元素用来占位,同时我们可以给这个元素加一个提示,这样我们既能通过代码判断是否滑动到底部,同时又给出了友好的提示。

let $loadmoreTip = document.querySelector('.loadmore-tip')
// 构建观察器
let observer = new IntersectionObserver((entries) => {
  for (let entry of entries) {
    /*
     * 检测节点是否可见,可以通过 isIntersecting 验证,布尔值
     * 如果目标元素与交叉区域观察者对象(intersection observer)的根相交,返回 true
     * 此时描述了变换到交叉时的状态; 
     * 如果返回 false, 那么可以由此判断,变换是从交叉状态到非交叉状态.
     * 同时也可以根据 intersectionRatio 验证
     * intersectionRatio:目标元素的可见比例
     * 即 intersectionRect 占 boundingClientRect 的比例
     * 完全可见时为1,完全不可见时小于等于0
     * 如果不可见,就返回:
     *   if (entry.intersectionRatio <= 0) return;
     */
    if (entry.isIntersecting === true) { // 检测节点是否可见
      // 处于交叉可见状态
      loadmore()
    }
  }
}, { threshold: 0.6 });

// 往观察器列表注册观察元素
observer.observe($loadmoreTip);