头几天官网刚上线,就接到投诉说有问题。过去一看,我靠什么鬼?!Mac下用触控板一滑到底,——首页上用iscroll写的翻页效果直接全军覆没。javascript
这个bug来的莫名其妙,问了一圈人也没什么思路,后来本身上网搜,在一个页面上找到一段关于Mac的触控板的手势滑动会疯狂触发滚轮事件的记录,可是轮到具体的解决方案就语焉不详了。没辙,靠天没用,仍是靠本身吧~java
这里先简单介绍下。出问题的首页用的是iscroll插件,用snap
属性作的整屏翻页的效果,翻页用鼠标滚轮驱动,这块用的是MDN上的一个滚轮事件的兼容代码,回调使用iscroll的接口完成向上/向下翻页的效果。git
回到这个问题上。一开始我想用事件防抖解决,因而用setTimeout()
本身写了个:触发事件后先进入延时,延时后执行函数;若是在延时内仍有事件触发,则取消原有的延时从新计时。浏览器
// 打底用的zepto.js,addWheelListener是滚轮事件的兼容插件,下同~ var wheelTimer = false; var wheelSlide = function (e) { e.preventDefault(); clearTimeout(timer); if (e.deltaY > 0) { wheelTimer = setTimeout(function(){ iScroll.next(); }, 100); } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) { wheelTimer = setTimeout(function(){ iScroll.prev(); }, 100); } } addWheelListener($('body')[0], wheelSlide);
我本意是用延时抵消掉重复触发的滚轮事件,最后合成一个事件触发,没想到测试以后,Mac上的问题并无解决。ide
因而我想,用事件防抖的思路处理应该仍是不对,即使是延迟时间较短,若是事件持续触发的话确定翻页仍是会被无限的延迟阻塞掉,至此我想换用事件节流再试试。在找资料的时候,意外发现了Underscore.js这个工具库,里边不只有现成的节流和防抖(中文文档里用的是“防反跳”)函数能够用,并且还支持链式调用,而且压缩版本也才十几k,正合我意。函数
说干就干,立刻用Underscore撸了个事件节流版的:工具
var wheelSlide = _(function (e) { e.preventDefault(); if (e.deltaY > 0) { iScroll.next(); } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) { iScroll.prev(); } }).throttle(400);//这里毫秒数用了400,大概至关于一个短动画的执行时间 addWheelListener($('body')[0], wheelSlide);
链式写法看上去还挺不错的!进本机浏览器(PC)……嗯?为啥最后会跳一下?赶忙翻文档,又加了个参数上去:测试
var wheelSlide = _(function (e) { e.preventDefault(); if (e.deltaY > 0) { iScroll.next(); } else if (e.deltaY < 0 && iScroll.currentPage.pageY != 0) { iScroll.prev(); } }).throttle(400, {trailing: false}); addWheelListener($('body')[0], wheelSlide);
这回PC上却是正常了,Mac也从一滑到底变成了有“段落感”的跳动,但结果仍是不对……
一狠心把毫秒数改为了5000,结果呢:还、是、不、对、、、。。。
(//陷入循环懵逼状态ing……)
痛定思痛,必定是文档看的不够多!因而又啃了一遍Underscore.js的文档(虽然是翻译的,囧……),发现防抖竟然有个[immediate]
参数,是能够优先执行的!大喜过望~接着撸:动画
var wheelSlide = _(function (e) { e.preventDefault(); if (e.deltaY > 0) { wScroll.next(); } else if (e.deltaY < 0 && wScroll.currentPage.pageY != 0) { wScroll.prev(); } }).debounce(600, true);// 原本想改回400的,有点心虚因此又加了200…… addWheelListener($('body')[0], wheelSlide);
竟然PC和Mac都能一页页的翻页了有!没!有!不过翻页的动做还有点迟滞,因而果断把毫秒数改小:400、200、100,……Bingo!插件
最终代码:
var wheelSlide = _(function (e) { e.preventDefault(); if (e.deltaY > 0) { wScroll.next(); } else if (e.deltaY < 0 && wScroll.currentPage.pageY != 0) { wScroll.prev(); } }).debounce(50, true); addWheelListener($('body')[0], wheelSlide);
总结:
Mac触控板bug踩坑 +1;
理解了事件节流和事件防抖的概念;
Underscore.js真好用;
感谢git把每次的修改都记了下来。