jQuery实现网页无限上拉

无限上拉,说起来很高端,实际就是 APP 里边的上拉加载更多。

现在做的一个小 Web 项目里刚好有这个需求,之前我做的 Web 应用都是通过翻页来查看其他内容的,没有做过这种加载更多的功能,所以刚好借这个机会接触下。

在没做之前,想的是加载更多可能就跟手机 APP 那样,通过 js 异步加载 json 数据,然后更改 DOM 来完成这个操作。于是我就昂首阔步开始做了,刚开始想通过 vue.js 来完成,整个页面都是通过 json 数据来渲染,后来遇到各种问题,(比如,通过url来过滤数据,/tag/xxx 过滤出 tag 为 xxx 的数据,但是没有找到非常便捷的方法来传递这个值给接口)所以放弃,再然后想要不就第一页通过 jinja 来渲染出来,剩下的页通过 jQuery 来加载,然后还是感觉各种麻烦。

这时候想到了谷歌,查找资料后发现一个 jQuery 插件是专门来实现这个需求的,而且实现方法跟我设想的完全不一样,大致原理是:就像做普通翻页那样,告诉它下一页的地址,再告诉它需要加载更多部分的节点,这个插件会异步请求那个页面,然后把相应部分取出,加载到当前页面的底部。

我了个擦,我居然没有想到这种方法,我之前设想方法,还要单独去写个用来翻页的接口,增加了很多工作量,这种方法简直是棒呆了!

下边来介绍一下这个插件的使用:

插件名称:infinite-scroll

项目地址: Infinite Scroll jQuery Plugin

参考地址: http://ifxoxo.com/jquery-infinite-scroll.html

首先要在页面底部新增一个类似于下一页按钮的部分,这个部分用什么包裹都可以,但最里边需要有个a标签,href对应的是下一页的地址。例如: <a id="next" href="?page=2"></a> 我这里什么也没有包裹,而且 a 标签里也没加文字,这样翻到底部时看不到任何提示信息。这里可以自行写个 div 什么的,里边写着上拉加载更多这样的提示信息。当加载更多被触发时,这个部分会自动隐藏掉。

下边来看看 js 代码部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$(document).ready(function () {
$("#masonny-div").infinitescroll({
navSelector: "#next:last", // 页面分页元素(成功后会被隐藏)
nextSelector: "a#next:last", // 需要点击的下一页链接
itemSelector: "div.section", // ajax回来之后,每一项的selecter
animate: true, //加载完毕是否采用动态效果
extraScrollPx: 100, //向下滚动的像素,必须开启动态效果
debug: true, //调试的时候,可以打开,
path: function (index) {
return "?page=" + index;
},
loading: {
finished: undefined,
finishedMsg: '没有更多内容了', //当加载失败,或者加载不出内容之后的提示语
img: '/static/pic/loading-new.gif', //自定义loadding的动画图
msgText: '正在加载中...', //加载时的提示语
}
});
})
;

因为我这里需要提取出来加载更多的部分是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="col-xs-12 section">
<div onclick="location.href='{{ artcle.url }}'">
<div><h4><a>{{ artcle.title }}</a></h4></div>
<div class="content">{{ artcle.abstract }}</div>
</div>
<div class="row tag">
<div class="col-xs-6">
<div class="row" style="white-space:nowrap;">
{% for tag in artcle._tags[:3] %}
<div class="col-xs-4" onclick="location.href='/tag/{{ tag.tag_id }}'">#{{ tag.name }}</div>
{% endfor %}
</div>
</div>
<div class="col-xs-4 col-xs-offset-2"
style="text-align: end">{{ artcle.publish_date | datetime('date') }}</div>
</div>
</div>

所以我的 itemSelector 的值为 div.section

还有一点,我这个用这个插件的时候,刚开始的时候一直有问题,是因为没有给 path 写值, path 的作用是每次加载下一页的时候所对应的地址。

还可以给加载更多时候的 loading 编写样式,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#infscr-loading {
text-align: center;
z-index: 100;
position: fixed;
left: 45%;
bottom: 40px;
width: 200px;
padding: 10px;
background: #000;
opacity: 0.8;
color: #FFF;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

至此,我又 get 到一个新技能。