无限上拉,说起来很高端,实际就是 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 到一个新技能。