页面很简单,先上效果图
吐槽
某日,暴雨,南京的某个角落
领导: 排面,来一下,我有一个小想法 。
我:怎么了,海哥,是不是有新功能要做,我等这一天好久了(MMP 就你想法多,听听歌撩撩妹不好吗)。
领导: 最近用户也突破120万了,项目处在稳定的维护期,所以我想新增加一个小功能 。
我: 什么功能你说吧,作为高级工程师,公司的颜值担当,没有什么是我解决不了的。
领导:我想做个一键洗车功能,给用户展示附近的洗车场,然后提供导航。用 h5实现,后期方便更新维护,你来写 h5和 iOS 。
我:(What?那我的王者荣耀怎么办)恩,您真是有远见,站在用户角度考虑。但我们产品和 UI 刚离职,没有原型和效果图,所以这个想法是不是有点不成熟 。
领导:只要有梦想,人人都是设计师 。
我:(ZZ....)
第二天来公司,我就收到了一副惨无人道的效果图,它大概是这个样子
我怎么怎么办,我也很绝望啊。
正文
前面加载数据的基本操作不做过多描述,直接进入正题。
判断上拉条件
此处后台接口除了返回一个头部信息外 + 10条列表数据,此时的参数 pagenum 为1。当上拉到页面底部时,再发一次 ajax 请求,参数 pagenum为2,以此类推。那么,怎么判断页面刚好到了底部。
假设此时是刚加载完数据的初始状态,可以看到还有一部分数据没有加载出来,处在在屏幕外。当此时手指往上滑动,进入下图这个状态。
所以当监听页面的 touchmove事件。 所有内容高度 = 屏幕高度 + 滑动高度时 。发送 ajax 请求,加载下一页数据。
windowH = $(window).height();
scrollH = $(document).scrollTop();
documentH = document.documentElement.scrollTop==0? document.body.scrollHeight : document.documentElement.scrollHeight;
if (windowH + scrollH >= documentH - 20) {
console.log("这里页面到达底部");
//执行 ajax 操作
$.ajax({
datatype : "JSON",
type : "POST",
url : "jiekou.htm",
timeout : 15000,
async:true,
data : { key:value,pagenum:pagenum},
error : function (e) {},
success : function(json) {
//for 循环加载数据
pagenum = parseInt(pagenum) + 1;
}
});
}
这里选择的是异步请求,同步请求当用户网络差或者我们服务器速度慢时,会卡死页面,并且需要等到timeout 之后才能进行下一次刷新加载,严重影响用户体验。
问题关键
但是此时出现了一个新的问题,当滑动到底部时,上面的输出语句 console.log("这里页面到达底部") 会调用数十次。因为 touchmove 事件一直响应,只要满足我们的判断条件,就会进入方法内执行输出语句。
因为我们前面选择的异步请求,所以ajax 请求也会执行数十次,就会出现大量的重复数据。解决这个问题有两个办法:
- 改为同步请求,一次加载未完成不会进行下一次请求。
- 继续使用异步,新增一个参数进行判断,当前后两次的pagenum不同才进行新的请求。
第一个方法直接放弃吧,不然会被领导搞死。
if (windowH + scrollH >= documentH - 20) {
if (pagenum != lastpangenum) {
//当此时的pagenum跟上一次不同时,才调用
lastpangenum = pagenum;//更新lastpangenum
//执行 ajax 操作
}
}
这样做得话问题好像已经被解决了。但是当你把 timeout 参数改的非常小,模拟网络差请求超时情况,发现 if (pagenum != lastpangenum) 条件永远不执行。因为没有走 success 方法,pagenum没有+1所以我们需要处理请求失败的情况。在 error 方法里打破 pagenum = lastpangenum 均衡。完整的代码如下:
if (windowH + scrollH >= documentH - 20) {
if (pagenum != lastpangenum) {
lastpangenum = pagenum;//更新lastpangenum
//执行 ajax 操作
$.ajax({
datatype : "JSON",
type : "POST",
url : "jiekou.htm",
timeout : 15000,
async:true,
data : { key:value,pagenum:pagenum},
error : function (e) {
lastpangenum = lastpangenum - 1;
},
success : function(json) {
//for 循环加载数据
pagenum = parseInt(pagenum) + 1;
}
});
}
}
小Tips
问题基本上就是这么多,作为一个非专业前端开发,一切还在摸索的过程中。这里放上几个常用的小方法,以备后用。
1,取当前URL 中的参数
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&#]*)/gi,
function(m,key,value) {
vars[key] = value;
}
);
return vars;
}
//用法(假设 url 为 www.baidu.com?guid=12345&token=kd1247da)
var guid = getUrlVars()["guid"];
2,获取时间戳,时间戳与正常格式转换
var nowtimestamp = new Date().getTime();//得到时间戳
var commentime = getLocalTime(nowtimestamp);//得到普通格式时间
function getLocalTime(ns) {
var d = new Date(ns);
var dformat = [ d.getFullYear(), d.getMonth() + 1, d.getDate() ].join('-')
+ ' ' + [ d.getHours(), d.getMinutes(), d.getSeconds() ].join(':');
return dformat;
}
3,Android平台与iOS平台判断
var u = navigator.userAgent;
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if(isAndroid ===true){
}else if(isiOS===true){
}
4,iOS返回不响应
<a href="#" onclick="window.history.back();return false;>
//在后面加return false,屏蔽 a 标签的默认操作
持续更新中...........
结语
整个功能做下来持续了一个多星期,也遇到过不少问题,对于 h5的很多底层原理知之甚少,更谈不上优化。最近在看俞甲子那本程序员的自我修养--链接、装载与库 发现自己对于一些底层知识越来越感兴趣,总觉得它像武林里的内功,一通则百通。好吧,扯得有点远了。等等.....领导好像又在叫我了.......