需求
只有一句话:下拉过程中实现加载下一页。
知识储备
在提出实现方案之前先来回顾一些简单的知识点:
event.target
触发事件的对象 (某个 DOM 元素) 的引用。当事件处理程序在事件的冒泡或捕获阶段被调用时,它与event.currentTarget不同。
event.target 属性可以用来实现事件委托:在ie中event.target写作event.srcElement。(Event.srcElement 是标准的 Event.target 属性的一个别名。它只对老版本的 IE 浏览器有效。)
offsetHeight
offsetHeight 属性是一个只读属性,它返回该元素的像素高度,高度包含内边距(padding)和边框(border),不包含外边距(margin),是一个整数,单位是像素 px。
即:offsetHeight = 元素可见高度 + padding + border
scrollTop
Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。
scrollHeight
Element.scrollHeight 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
解决方案
要实现下拉请求下一页的操作,关键点在于什么时候页面滑动到了最底端。换句话说就是当页面滑动到最底端的时候去加载下一页的内容。
那怎么判断页面是否滑动到了最底端呢:
(e.target.offsetHeight + e.target.scrollTop) - e.target.scrollHeight ===0
除此之之外还需要一个约束条件,那就是列表所有已请求回来的数据总数 < total。这样可以确保还有数据需要请求。若是只有两页数据,请求第三四五页数据就是徒劳的。当然这第二个约束条件是根据业务去自己定的。
代码实现
添加页面滑动监听事件:
mounted(){
window.addEventListener('scroll', this.scrollBottom, true);
}
当然记得移除监听事件,避免内存泄漏:
beforeDestroy() {
window.removeEventListener('scroll', this.scrollBottom, true);
}
滑动事件回调函数
scrollBottom(e) {
if ((e.target.offsetHeight + e.target.scrollTop) - e.target.scrollHeight ===0 && this.list.length < this.total) {
++this.page;
this.getList()
}
},
优化
后续测试过程中,发现在一个同事的电脑上下拉没有加载下一页,在拉到底端的时候,打印如下信息
e.target.offsetHeight 754
e.target.scrollTop 3142.39990234375
e.target.scrollHeight 3896
以上信息导致(e.target.offsetHeight + e.target.scrollTop) - e.target.scrollHeight === 0 永远为false 所以没有加载下一页。
所以将这个条件变成:
(e.target.offsetHeight + e.target.scrollTop) - e.target.scrollHeight < 1 && (e.target.offsetHeight + e.target.scrollTop) - e.target.scrollHeight >= 0