iScroll 4,把禁掉的:active样式还给我~

iScroll这个移动端的滚动神器大家都非常熟悉了,直到现在仍是实现移动端Web滚动的首选方案之一。。。

当我接触移动端Web时iScroll已经有两个版本了,iScroll 4和iScroll 5,当时看到很多文章都是关于iScroll 4的,看来这个版本已经得到的非常广泛的应用,而iScroll 5的文章相对非常之少,好吧,项目进度耽误不起,我们就选当前最流行的这个版本吧(iScroll 4.2.5),想必也是最成熟稳定的。。。

 

iScroll 4的官网地址:

http://cubiq.org/iscroll-4

 

这个插件的功能全面,使用也简单,应对表面统一的移动浏览器平台(我们只关注webkit核心~~ ^_^)感觉游刃有余,对于性能问题,使用初期也察觉到有什么异样(看来常年停留在安卓2.3系统的我根本不知道顺滑与卡顿的区别~~),心里还在莫莫崇拜国外牛人多啊~~ 

 

直到项目进入后期完善阶段了,就会到处点一点,按一按,检查下前端工作是否有重大Bug,突然间意识到有些页面表现怪怪的,一些Button点击时少了一点什么效果,原来是在点击按钮时没有表现出交互效果!

 

查看下CSS代码,明明我在.btn类上加了:active效果了的,而且在应用iScroll滚动的区域外的button是有效果的(我是用桌面Chrome模拟器的),那问题一定是出在iScroll身上了。。。其实这个问题也可以理解,在很多类似的模拟插件中如果不禁用掉系统默认事件或者效果的话,达不到完美的用户体验效果,印象中桌面端的那个mousewheel插件就是如此。。。

 

那我就看API,找度娘~~原来很早有很多人已经遇到这样的问题了,比如园里的Tony同学(http://www.cnblogs.com/lostyu/p/3907256.html)哈哈,有人进过坑,就意识着有人成功跳出过坑~~直接把解决方法拿来用是我们前端城狮的必要技术之一,于是我也复制之~~ ^o^  

 

iScroll作者当时一刀砍啊,所有默认行为全部干掉了:

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"
        });

 

posted @ 2015-04-29 18:01  木易宇飞  阅读(1382)  评论(0编辑  收藏  举报