解决iSlider的一些问题(滑动组件)

一:先解决一下该插件在PC端(针对数据内容是html)滑动性能的问题,反正就是在PC端滑动体验不好。

针对这个问题我先去监测了组件里滑动时evt.pageX , this.startX(鼠标按下去的)这两个的值变化,结果发现那个evt.pageX滑动到一定的距离后跟实际鼠标位置的值不匹配,在进一步才发现他提前执行了endHandler以至this.onMoving 设置成了false,然后后面就不会滑动了。

仔细看了下代码,组件给PC端执行了如下代码

 !device.hasTouch && outer.addEventListener('mouseout', this);//组件原本的mouseout事件代码

注:这里的this是该组件引用类型的实例,也就是该组件对象,这里传这个的用意请看,这里不在陈述

http://www.kuqin.com/shuoit/20131123/336495.html

其实仔细想想,就是绑定mouseout事件处理程序的原因,因为元素内部的html元素会触发mouseout将其冒泡到给事件绑定事件处理程序的容器。

然后我尝试阻止事件冒泡或采用事件捕获,(阻止事件捕获也没用),发现其实都没什么用,然后就查找资料看到了这篇文章

http://blog.csdn.net/ltx851201/article/details/6800553

然后我将其组件添加了如下代码

    /****对iSlider插件的PC版html滑动性能问题修复,主要是mouseout触发的endHandler事件处理程序的影响*
    *解决方法在触发mouseout事件处理程序是:先监测目标对象是否是绑定此事件处理程序对象本身(因为鼠标在目标对象的内部的元素移动时触发的mouseout会冒泡到目标对象)*
    ***辅助函数START********/
    iSliderPrototype.contains = function (parentNode, childNode) {
        if (parentNode.contains) {
            return parentNode != childNode && parentNode.contains(childNode);
        } else {
            return !!(parentNode.compareDocumentPosition(childNode) & 16);
        }
    }


    //这个函数用于检查一个对象是否被包含在我们的触发对象里面。
    //下面就是我们的重点了,我封装了一个用于检查鼠标是否真正从外部移入或者移出对象的函数checkHover(e,target),这个函数需要传入当前的事件对象和目标对象。
    iSliderPrototype.checkHover = function (e, target) {
        var e = e || window.event;
        if (e.type == "mouseover") {
            return !this.contains(target, e.relatedTarget || e.fromElement) && !((e.relatedTarget || e.fromElement) === target);
        } else {
            return !this.contains(target, e.relatedTarget || e.toElement) && !((e.relatedTarget || e.toElement) === target);
        }
    }
    /********对iSliderJS的PC版html滑动性能问题修复***辅助函数END******/

  

然后将之前绑定mouseout事件处理程序的代码改写成了这样

            if (!device.hasTouch) {
                var that = this;
                outer.addEventListener('mouseout', function (e) {                    
                    that.checkHover(e, outer) &&that.endHandler(e); 
                },false);
            }

至此该组件在PC端滑动体验好多了

二:解决滑动屏幕里的每个小容器点击问题

该组件在滑动的时候会触发click事件,影响交互。

解决方法

1.先给该组件添加一个回调函数,在实例化的时候传参进去,然后在原组件绑定事件之前先执行此回调函数,前端调用的时候这样调用,如下

参数里的beforeBindHandler就是我们传入的回调函数,此函数的作用是绑定mousedown和mouseup事件处理程序,
如果鼠标按下和放开间隔事件小于300毫秒则执行点击程序,否则不执行。
var isGoDetail = true;
			    var _iSliderWrapper = document.getElementById('iSlider-wrapper');

			    S = new iSlider({
			        dom: _iSliderWrapper,
			        data: list,
			        isLooping: 1,
			        isOverspread: 1,
			        onslide: function () {
			            isGoDetail = false;
			        },
			        onslidechanged: function (index) {
			            isGoDetail = true;
			            updateRange(itemWidth * index, index);
			        },
			        beforeBindHandler: function () {
			            var startTime;
			            var up = function (ev) {
			                if ((new Date().getTime() - startTime <= 300) && isGoDetail) {
			                    var ev = ev || window.event;
			                    var target = ev.target || ev.srcElement;

			                    //closest里面的选择器元素就是需要点击触发的每一个容器,可以事先在里面附加一些我们需要的信息
			                    var item = target.closest("div.div_newsWidthImg,.div_news_item");

			                    if (item.getAttribute("data-screenNum")) {
			                        var screenNum = item.getAttribute("data-screenNum");
			                        var order = item.getAttribute("data-newsOrder");
			                        window.location.href = "newsDetail.html?pScreenNum=" + screenNum + "&pNewsOrder=" + order+"&newsType=" + $(".div_nav_more>p").text();;
			                    }
			                } else {
			                    isGoDetail = true;
			                }
			            }

			            var down = function (e) {
			                startTime = new Date().getTime();
			            }

			            _iSliderWrapper.addEventListener("mousedown", down);
			            _iSliderWrapper.addEventListener("mouseup", up);
			        },
			        oninitialized: function () {
			            args["pScreenNum"] && this.slideTo(Number(args["pScreenNum"]) - 1);
			        }
			    });

  



注意closest方法用原生JavaScript替代jQuery的closest方法,目前只有现代浏览器本身就支持。如果需要兼容ie9(目前我测试至少在ie9及以上是OK的),则加入以下代码
//原文出处1:http://www.codesec.net/view/206139.html 2:https://plainjs.com/javascript/traversing/match-element-selector-52/
/*******匹配DOM上级元素,实现closest()方法,由于在现代浏览器中内置支持了这些元素,因此我们为了获得更好的性能,
我们建议在原生对象上进行拓展,就可以像下面这样直接使用:*********/
this.Element && function (ElementPrototype) {
    ElementPrototype.matches = ElementPrototype.matches ||
    ElementPrototype.matchesSelector ||
    ElementPrototype.webkitMatchesSelector ||
    ElementPrototype.msMatchesSelector ||
    function (selector) {
        var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
        while (nodes[++i] && nodes[i] != node);
        return !!nodes[i];
    }
}(Element.prototype);

this.Element && function (ElementPrototype) { ElementPrototype.closest = ElementPrototype.closest || function (selector) { var el = this; while (el.matches && !el.matches(selector)) el = el.parentNode; return el.matches ? el : null; 
} }(Element.prototype);

  

三.ie9滑动兼容性问题和样式问题

将_animateFuncs方法改写如下

  iSlider._animateFuncs = {
        normal: (function () {
            function normal(dom, axis, scale, i, offset) {
                // iSlider.setStyle(dom, 'transform', 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)');
                if (iSlider.TRANSITION_END_EVENT) {
                    iSlider.setStyle(dom, 'transform', 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)');
                } else {
                    dom.style.left = (offset + scale * (i - 1)) + 'px';
                }
            }

            normal.effect = iSlider.styleProp('transform');
            return normal;
        })()
    };

  改写后的组件代码链接:https://files.cnblogs.com/files/qiny-easyui/iSlider.js

原文地址:https://www.cnblogs.com/qiny-easyui/p/5708556.html