这里涉及到了多种尺寸值,包括 scrollTop 、 offsetTop 、 clientHeight 、 scrollHeight 等等,如果不清楚的话整个函数的逻辑就很难看懂,关于它们的具体意义可以参考我之前写的一篇博客。
这里我用两幅图来辅助理解上面的逻辑,相信会好懂很多。
滚动元素是自身
如下,我们的目标是判断元素是否已滚动到底部的距离阈值之内,很容易可以看出来,距离内容底部的距离公式为:
const { scrollHeight, clientHeight, scrollTop } = scrollEventTarget; const currentDistance = scrollHeight - clientHeight - scrollTop;
这也就是函数 if 分支的逻辑,当 currentDistance 小于 distance 时,我们就可以加载下一页数据了。
父级元素设置滚动
此时就没有 scrollTop 属性可以操作了,但是元素的高度仍然可以用上面的属性:滚动父元素的高度可以用 scrollEventTarget.clientHeight ,子元素内容高度可以用 element.offsetHeight ,剩下的就是计算 topGap 了。
我们知道 DOM 的坐标有两种:文档坐标、视口坐标,计算 topGap 只要始终在其中一个坐标系计算就可以了,这里我们采用视口坐标。 ele.getBoundingClientRect().top 可以知道一个元素距离视口顶部的距离,那么 topGap 的计算公式就是:
const topGap = scrollEventTarget.getBoundingClientRect().top - element.getBoundingClientRect().top;
综上,子元素底部与父元素底部的距离公式就是:
const currentDistance = element.offsetHeight - scrollEventTarget.clientHeight - (scrollEventTarget.getBoundingClientRect().top - element.getBoundingClientRect().top);
这也就是函数的 else 分支逻辑。
以上就是 doCheck 的核心检测逻辑了,同时针对 scrollEventTarget 为 document 时做了一些特殊处理,留给大家自己去看。