浅析无限滚动加载

无限滚动加载算是一个比较常见的功能了,今天以原生js的形式分析一下原理,一般来说,要实现无限滚动加载常见的有以下两种方法。

监听滚动事件

这一种兼容性比较强,但是处理较为繁琐,有时还要搭配防抖一起使用,前置知识为 clientHeight :表示外围div的高度,即可视高度 offsetHeight /scrollHeight :表示内容的高度 scrollTop :表示滚动条可以滚动的高度,举个例子,比如有一个div,它的高度是100px,那么clientHeight=100px;比如这个div 里面的的内容很多,内容的高度为200px,那么offsetHeight = 200px,就是说我们只能看到100px的内容,还有100px的内容是看不到的,只能通过滚动条拉动来查看,scrollTop的范围在[0,100]之间,当滚动条顶部的位置是100px时就是说明滚动条拉到底了。
核心代码如下

function touchScroll() {
  let offsetHeight = Math.max(box.scrollHeight,box.offsetHeight); // 内容高度
  let clientHeight = window.innerHeight || document.documentElement.clientHeight || box.clientHeight || 0; //视窗高度
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || box.scrollTop || 0; //滚动条滚动高度
  return (offsetHeight - clientHeight - scrollTop)
}

window.onscroll=function(){
  let touchScroll = this.touchScroll()
  if(touchScroll < 0) {
      // 发送请求加载
      console.log('我到底啦')
  }
};

实际效果如下

windowOnscroll.gif

上面的那种适用于全屏下拉加载,所以直接监听 window 上面的 onscroll 事件即可,但是大部分时候页面都不是那么简单的,更多的时候是嵌套加载,
那么这个时候就不能监听 window 了,这个时候需要直接监听DOM上的onscroll事件了,核心代码如下

box.addEventListener('scroll', function (e) {
 let offsetHeight = Math.max(this.scrollHeight, this.offsetHeight); // 内容高度
 if (offsetHeight - this.clientHeight - this.scrollTop < 10) {
   console.log("我到底啦")
 }
});

实际效果如下

boxOnscroll.gif

elementui中的InfiniteScroll组件也是这么处理的,不过它是结合着防抖一起做的
elementui.png

IntersectionObserver API

IntersectionObserver 是16年发布的Chrome 51上新出的API,可以自动"观察"元素是否可见 上面的源码就可以简化为下面这几行:

const bottomBox = document.getElementById("bottom-box")

const io = new IntersectionObserver(entries => {
  const isIntersecting = entries.find((entry) => {
    console.log(entry.isIntersecting)
  })
})

io.observe(bottomBox)

效果如图所示


IntersectionObserverAPI.gif

在嵌套滚动中的使用方法也是一样的,效果如下


IntersectionObserver-1.gif

很明显,在使用上,我们对比第一种方法,第二种方法简直便捷的过分,既不需要计算,更不需要防抖之类的操作,详细使用方法如下:
const io = new IntersectionObserver(callback, option);

IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(可选)

// 开始观察
io.observe(document.getElementById('example'));

// 停止观察
io.unobserve(element);

// 关闭观察器
io.disconnect()

最后是兼容性,目前主流的pc端浏览器已全面支持(ie除外,不过它的profile现在也出来了,详见github),大家可以放心使用

mdn-IntersectionObserver.png

你可能感兴趣的:(浅析无限滚动加载)