下拉刷新、上拉加载更多是移动端常见的交互效果,也有很多封装好的库供我们方便的调用。但是如果只是一个简单的临时页面,也许不用第三方库手写实现会是一个不错的选择。今天就来简单说说上拉加载更多的实现思路。
分析
把上拉加载更多这个过程拆解一下,可以分成这几个步骤:
- 页面向下滚动…
- 页面滚动到了底部
- 此时,显示加载动画,并发送ajax请求
- 在请求成功后,隐藏加载动画,填充数据
通过以上步骤,不难发现,这个过程最关键的一步就是判断是否滚动到底部了。要完成这个判断,需要先来了解一下三个长度单位的概念:
- 文档高度:即整个网页内容的实际高度,这部分高度可能会有一部分是现在看不到,需要滚动一下滚动条才能看到的。
- 视口高度:即你能在浏览器里看到的网页内容的区域的高度。调整浏览器窗口的高度这个值会随之变化。
- 滚动条位置:准确来讲是窗口垂直滚动条距离顶端的距离。
如果滚动条滚动到了底部,它们之间满足这个公式:文档高度 - 视口高度 - 滚动条位置 == 0
。为了方便DOM操作,省去繁琐的兼容处理。使用jQuery来表示:$(document).height() - $(window).height() - $(window).scrollTop() == 0
。
踩坑
搞清楚了关键的一步,似乎挺简单的,是时候用代码来实现上面的过程了:1
2
3
4
5
6
7
8
9<div class="list">
<ul>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
...
<ul>
</div>
1 | $(function(){ |
以上的demo用定时器模拟了ajax请求获取数据的操作,似乎没有什么问题,但是实际运行的时候,滚动到底部的时候,会看到在列表底部追加了多个加载中...
节点。这说明if
语句块执行了多次,这是因为$(winow).scroll()
是以一个很高频率被触发的,比如说滚动滚轮的时候,一秒钟内可能执行了多次$(winow).scroll()
。要解决这个问题,需要添加一个全局标识isEnd = false;
在滚动到底部时isEnd = true;
,然后在请求完成,新的数据渲染完毕时再isEnd = false;
,并且在上面的if
语句块之前进行这个标识的判断if isEnd return;
升级
踩了一遍坑之后,把上面的代码升级一下(另外把加载中的添加移除节点改为显示和隐藏)。1
2
3
4
5
6
7
8
9
10<div class="list">
<ul>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
<li>这是一条新闻</li>
...
<ul>
<div class="loading" style="display:none;">加载中...</div>
</div>
1 | $(function(){ |
当然了,这只是一个简单的实现思路,还有很多需要优化的地方,比如移动端的滚动问题…
结语
上面的内容很基础,但也是自己学习的一个总结吧,有错误的地方还望指正。最近比较浮,面对更新迭代如此迅速的前端,感觉有点无所适从。听说vue3都快要到来了,而我却还没有用vue写过一个完整的项目。ES都到ES7,ES8了,而我还在用ES5。焦虑只会让事情变得更糟,所以有一句话希望与和我一样的小白共勉:不要停下来,但要记住:慢下来,才最快。