iScroll这个移动端的滚动神器你们都很是熟悉了,直到如今还是实现移动端Web滚动的首选方案之一。。。html
当我接触移动端Web时iScroll已经有两个版本了,iScroll 4和iScroll 5,当时看到不少文章都是关于iScroll 4的,看来这个版本已经获得的很是普遍的应用,而iScroll 5的文章相对很是之少,好吧,项目进度耽误不起,咱们就选当前最流行的这个版本吧(iScroll 4.2.5),想必也是最成熟稳定的。。。 前端
iScroll 4的官网地址:node
这个插件的功能全面,使用也简单,应对表面统一的移动浏览器平台(咱们只关注webkit核心~~ ^_^)感受游刃有余,对于性能问题,使用初期也察觉到有什么异样(看来常年停留在安卓2.3系统的我根本不知道顺滑与卡顿的区别~~),内心还在莫莫崇拜国外牛人多啊~~ 浏览器
直到项目进入后期完善阶段了,就会处处点一点,按一按,检查下前端工做是否有重大Bug,忽然间意识到有些页面表现怪怪的,一些Button点击时少了一点什么效果,原来是在点击按钮时没有表现出交互效果!app
查看下CSS代码,明明我在.btn类上加了:active效果了的,并且在应用iScroll滚动的区域外的button是有效果的(我是用桌面Chrome模拟器的),那问题必定是出在iScroll身上了。。。其实这个问题也能够理解,在不少相似的模拟插件中若是不由用掉系统默认事件或者效果的话,达不到完美的用户体验效果,印象中桌面端的那个mousewheel插件就是如此。。。
性能
那我就看API,找度娘~~原来很早有不少人已经遇到这样的问题了,好比园里的Tony同窗(http://www.cnblogs.com/lostyu/p/3907256.html)哈哈,有人进过坑,就意识着有人成功跳出过坑~~直接把解决方法拿来用是咱们前端城狮的必要技术之一,因而我也复制之~~ ^o^ 学习
iScroll做者当时一刀砍啊,全部默认行为所有干掉了:spa
onBeforeScrollStart: function (e) { e.preventDefault(); }
你们的解决方法:插件
onBeforeScrollStart: function (e) { var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase() : ( e.target ? e.target.nodeName.toLowerCase() : '' ); if( nodeType != 'select'&& nodeType != 'option' && nodeType != 'input' && nodeType != 'textarea' ) e.preventDefault(); }
这个方法很直接,颇有效,将最为经常使用的系统组件select、option、input、textarea等等在iScroll中点击无效的问题解决了;
可是若是咱们想让Button也能点击且有点击效果的话,就要手动再加 && nodeType != 'button' 到代码里去,也行吧~~~
可是若是咱们想让<a class="btn">也有点击效果~~~,就要进一步改造啦。
对了,不是有iScroll 5了吗,它会不会有这个问题呢?看一下API, 新版本已经有相关的控制参数了: options.preventDefaultException
iScroll 5官网API:
http://iscrolljs.com/#advanced-options
要不直接换iScroll 5? 了解过iScroll 5的同窗要先呵呵一下,由于iScroll 5已经不是4+1=5那么简单了。
iScroll 5已经彻底重写了,很多接口都作了改变,就连实例化的方式都不一样了,这么说吧,iScroll 4与5彻底是两个东西,你甚至能够在同一个页面中同时使用它们俩:
iScroll 4使用:
new iScroll('scroll-wrapper-1');
iScroll 5使用:
new IScroll('#scroll-wrapper-2');
iScroll 5提供的那个配置接口参数能够解决咱们以前遇到的问题:
new IScroll('#pro-detail',{ preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/, className: /(^|\s)btn(\s|$)/ } });
看到 className: /(^|\s)btn(\s|$)/ 了吗? 这样就可使.btn的元素不被preventDefault()方法干扰。
因为换用iScroll5的劳动成本略大于对iScroll4的改进(实际上是不改内心有点难受,我不是处女座),咱们开始改动工~
咱们学习iScroll 5的样子,为iScroll 4也添加配置参数(大概在107行):
// Default options
that.options = { hScroll: true, vScroll: true, x: 0, y: 0, bounce: true, bounceLock: false, momentum: true, lockDirection: true, useTransform: true, useTransition: false, topOffset: 0, checkDOMChanges: false, // Experimental
handleClick: true, preventDefaultException: "", // ex: "A|BUTTON|.btn-class|#btn-id"
。。。
而后将那个onBeforeScrollStart方法在同窗们改造过的基础之上变得更丰满,以下:
onBeforeScrollStart: function (e) { var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase() : (e.target ? e.target.nodeName.toLowerCase() : ''); var excpt = that.options.preventDefaultException.replace(/\s/g, ""), excptArr = null, targetNode = null; if (nodeType != 'select' && nodeType != 'option' && nodeType != 'input' && nodeType != 'textarea' && !isExcptNode(e.target, excpt)) { e.preventDefault(); } function isExcptNode(_node, _excptStr) { var result = false; if (_excptStr) { targetNode = _node; excpt += _excptStr.match("|") ? "" : "|"; excptArr = excpt.split("|"); for (i in excptArr) { if (targetNode.nodeName.toString().toLowerCase() == excptArr[i].toLowerCase()) { result = true; break; } else if (excptArr[i].match("#")) { if (targetNode.id.match(excptArr[i].replace("#", ""))) { result = true; break; } } else if (excptArr[i].match(".")) { if (targetNode.className.match(excptArr[i].replace(".", ""))) { result = true; break; } } } } return result; } }
因而,咱们也能够在使用iScroll4时这样啦:
new iScroll('wrapper', { useTransition: false, vScrollbar: false, preventDefaultException:".btn|.btn-b|#btn-submit" });