关于iScroll插件在某一些手机上滑动卡顿或者不滑动的处理

前几天在帮一个同事看了个问题,就是他的老项目里(用的jquery)写的,用iScroll插件作滚动加载的时候,在他的iphone7手机上,指定区域只能移动6px左右,这明显不正常,其余同事包括个人(8plus)是正常的,而后帮他找缘由, 首先查看了下iScroll的版本4.25,好像也没问题啊。jquery

1、 问题分析

一、onBeforeScrollStart方法:

onBeforeScrollStart: function(e) {
    e.preventDefault(); 
}
复制代码

此方法是在_start里进行了调用,目的是为了阻止浏览器默认动做的执行,防止在滑动的过程当中进行干扰,同时也就阻止了滑动区域里元素的事件的触发,这种处理方式也直接致使了必需要在_end方法中再次触发元素的点击事件。android

二、_end方法

if (target.tagName != 'SELECT' && target.tagName != 'INPUT'
&& target.tagName != 'TEXTAREA') {
    ev = document.createEvent('MouseEvents');
    ev.initMouseEvent('click', true, true,
    e.view, 1,point.screenX,
    point.screenY, point.clientX,
    point.clientY,e.ctrlKey,
    e.altKey, e.shiftKey,
    e.metaKey,0, null);
    ev._fake = true;
    target.dispatchEvent(ev);
}
复制代码

这个处理方式就是顺承了上面所提到的阻止了浏览器默认行为后,对滑动区域除select、input、textarea外的元素触发click事件,已完成对click绑定事件的调用。web

2、 具体分析

因为onBeforeScrollStart是在_start方法中进行的调用,e.preventDefault();阻止了元素的默认行为,从而致使了元素绑定事件的失效,必须在_end操做结束后进行绑定事件的模拟调用,原始的iScroll源代码中在_end中最后建立了click事件的模拟,可是这里必需要清楚的一个原理就是,click实际上是要依赖于其余事件的:chrome

  • 1 普通pc网页中,click须要依赖于mousedown、mouseup的相继触发浏览器

  • 2 移动webkit中,click则须要依赖于touchstart、touchend(实际mousedown,mouseup在移动webkit上也存在)的相继触发 “相继触发”的意思就是中间不会夹杂有其余的事件类型,这也就很容易理解iScroll中在_end中对模拟事件调用的条件了,必需要判断that.moved才能直接触发模拟事件。bash

iScroll中与_start、_move、_end相关的三个事件类型是按照以下的规则来设置的:框架

START_EV = hasTouch ? 'touchstart' : 'mousedown'
MOVE_EV = hasTouch ? 'touchmove' : 'mousemove'
END_EV = hasTouch ? 'touchend' : 'mouseup'
复制代码

3、 具体说明

经测试,部分手机里默认浏览器里会默认全部元素都有一个默认的click事件(测试结果显示鼠标事件中默认事件包含mouseup,mousedown,click,dblclick在移动webkit上不支持,为系统放大功能),e.preventDefault时会阻止掉默认click事件的执行,必需要人为的在_end结束以后模拟click事件的调用,而其余正常手机即便调用了e.preventDefault也不会阻止click事件的触发,由于这些手机的默认浏览器上的元素的click事件的cancelable属性不为true,不能够被preventDefault取消掉,会正常执行,而若是在_end中模拟了click事件则将会致使click的重复调用(在有toggle状态的事件上很是明显),所以折中的方式参见下面的解决方案。iphone

4、 解决方案

1. 去除onBeforeScrollStart里的阻止默认行为:

onBeforeScrollStart: function (e) {
   //e.preventDefault(); 
}
复制代码

2.onBeforeScrollMove设置为:

onBeforeScrollMove:function (e) {
  e.preventDefault();
}
复制代码

以保证手机上的正常滑动免受浏览器默认行为影响(以下滑时会有窗口的scroll事件),固然若是这里不添加的话也能够在document的END_EV中阻止浏览器默认行为测试

3. _end 中将模拟事件名更改成END_EV或者直接去掉模拟事件的功能

iscroll.js是Matteo Spinelli开发的一个js文件,使用原生js编写,不依赖与任何js框架。旨在解决移动webkit系浏览器的区域滚动问题,兼容mobile、safari、android默认浏览器、safari、chrome、firefox5+、opera11+、IE9+及其余webkit核心浏览器。spa

五、最后说明

最后,我在这次解决滚动失效的过程当中,针对该页面作了一个最简单的处理以下:

//  获取所须要滚动区域的元素
    var scrollPage = document.querySelector('.scrollPage');
//  取消事件默认动做
    scrollPage.addEventListener('touchmove',function(e){
        e.preventDefault();
    });
复制代码

这样页面便可恢复滚动效果了。

相关文章
相关标签/搜索