原理
1.通过监听滚动区域DOM的scroll事件, 计算出触底
// 滚动可视区域高度 + 当前滚动位置 === 整个滚动高度
scrollDom.clientHeight + scrollDom.scrollTop === scrollDom.scrollHeight
2.触底后触发列表添加, 列表添加使用createDocumentFragment, 将多次插入的DOM先存入内存, 最后一次填充进去, 提高性能, 也方便后面的MutationObserver监听
3.使用MutationObserver监听列表的DOM添加, 添加完毕后, 隐藏加载中提示
示例
https://codepen.io/klren0312/full/dybgayL
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/clientHeight
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollHeight
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollTop
https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalEventHandlers/onscroll
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createDocumentFragment
https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
背景: js实现滚动条一直在底部靠的是元素的scrollTop和scrollHeight来实现的,可是在React中有些行不通。
原理: 在容器的底部添加一个空的div,使该div一直处于浏览器视口内,这样就可以让容器的滚动条位于底部。
知识点:
useState: 通过在函数组件里调用它来给组件添加一些内部 state, useState 唯一的参数就是初始 state
useEffect: 给函数组件增加了操作副作用的能力,它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。
useRef: 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
Element.scrollIntoView() : 让当前的元素滚动到浏览器窗口的可视区域内。
方案一:用hooks实现
方案二:用类组件实现
个人推荐第一种方案,第二种方案可行但是操作DOM性能一般。
先上原理图:
判断滚动条是否到临近页面底部,关键是求得上图中 ? 的数值,明显看出这个值 = 文档总高度 - 已滚动部分的高度 - 当前视口高度,所以有如下代码:
var minAwayBtm = 100 // 距离页面底部的最小距离$(window).scroll(function() {
var awayBtm = $(document).height() - $(window).scrollTop() - $(window).height()
console.log('当前距离页面底部:' + awayBtm + 'px')
if (awayBtm <= minAwayBtm) {
console.log('触发了')
}
})