vue-下拉加载下一页

642 阅读1分钟

需求

只有一句话:下拉过程中实现加载下一页。

知识储备

在提出实现方案之前先来回顾一些简单的知识点:

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 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。

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